#include "bmpfile.h"

#include <cstdlib>
#include <QRegExp>
#include <QDataStream>

BMPFile::BMPFile()
{
    reset();
}

BMPFile::~BMPFile()
{
    delete[] m_pBuf;
    m_pBuf = nullptr;
}

BMPFile::BMPFile(const QString &fileName):
    m_filePathName(fileName)
{
    reset();
}

bool BMPFile::compare(CharacterVector *pCharactor, double &similarity)
{
    //check
    if( nullptr == pCharactor)
    {
        qWarning() << "nullptr";
        return false;
    }
    if( !start())
    {
        return false;
    }
//    qDebug() << "Will compare";
    similarity = Compare(m_pChara,CHARACTER_LENGTH,
        pCharactor,CHARACTER_LENGTH);
    return true;
}

bool BMPFile::compare(BMPFile &other, double &similarity)
{
    if( !start())
    {
        return false;
    }
    if( !other.start())
    {
        return false;
    }
    similarity = Compare(m_pChara,CHARACTER_LENGTH,
        other.m_pChara,CHARACTER_LENGTH);
    return true;
}

bool BMPFile::binarizing(char* pOutChar, int& nOutLen)
{
    if( m_iIsFinished)
    {
        return true;
    }
    if(!m_iIsInitiliztion)
    {
        init();
    }
    //qiu huidu value
    if( !threshold() )
    {
        qWarning() << "error";
        return false;
    }

    //malloc
    const long lWidth = m_infoHeader.biWidth;
    const long lHeight = m_infoHeader.biHeight;
    char* lpRecorder = new char[
            m_infoHeader.biWidth *
            m_infoHeader.biHeight];
    if( nullptr == lpRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpRecorder,1,lHeight*lWidth);
    if( !pupilContour(lpRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    listPoint_type PointListForPHT;
    if( !findPHTPoint(lpRecorder,PointListForPHT) )
    {
        qWarning() << "error";
        return false;
    }
    //check
    if(PointListForPHT.isEmpty())
    {
        qWarning() << "Not suppert picture or is too much mohu";
        return false;
    }
    CIRCLE InnerCircle;
    if( !PHT(PointListForPHT,InnerCircle) )
    {
        qWarning() << "error";
        return false;
    }
    CIRCLE OuterCircle;
    if( !findOuterCircle(InnerCircle,OuterCircle) )
    {
        qWarning() << "error";
        return false;
    }
    //delete
    delete[] lpRecorder;
    lpRecorder = nullptr;

    const uint32 RectWidth=512;
    const uint32 RectHeight=128;
    char* lpNewRecorder = new char[
            RectWidth * RectHeight +
            m_fileHeader.bfOffBits];
    if( nullptr == lpNewRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpNewRecorder,0,
           RectWidth*RectHeight + m_fileHeader.bfOffBits);
    memcpy((void*)lpNewRecorder,
           (const void*)m_pBuf,
           m_fileHeader.bfOffBits);

    //update width and height
    char* pTemp = lpNewRecorder;
    pTemp += 2;
    uint32* pUint32 = (uint32*)pTemp;
//    qDebug() << *pUint32;
    *pUint32 = RectWidth * RectHeight +
            m_fileHeader.bfOffBits;
    pTemp = lpNewRecorder + BMP_FILE_HEADER_SIZE;
    pTemp += sizeof(m_infoHeader.biSize);
    pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth;
    ++pUint32;
    *pUint32 = RectHeight;

    pTemp = lpNewRecorder + BMP_FILE_HEADER_SIZE + 20;
    pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth * RectHeight;
    ++pUint32;
//    qDebug() << "biXPelsPerMeter:" << *pUint32;
    ++pUint32;
//    qDebug() << "biYPelsPerMeter:" << *pUint32;

//    qDebug() << "biXPelsPerMeter:" << m_infoHeader.biXPelsPerMeter;
//    qDebug() << "biYPelsPerMeter:" << m_infoHeader.biYPelsPerMeter;

    if( !TurnToRect(InnerCircle,OuterCircle,lpNewRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    LOGBin(lpNewRecorder);
    Morphological(lpNewRecorder);

//    int tab = 0;
//    PointInformation pointInfor[255];
//    MarkthePoint(lpNewRecorder, pointInfor, tab);
//    CharacterVector CharaV1[CHARACTER_LENGTH];
//    GetCharacterVector(pointInfor, tab, CharaV1, CHARACTER_LENGTH);
//    //存储特征向量
//    FileName_Chara FileCharaV1;
//    FileCharaV1.FileName = "source.txt";
//    FileCharaV1.Chara = CharaV1;
//    MySaveCharaV(FileCharaV1, CHARACTER_LENGTH);

//    memcpy(m_pChara,CharaV1,sizeof(m_pChara));

////    m_hDIBTarget = lpNewRecorder;

//    delete[] lpNewRecorder;
//    lpNewRecorder = nullptr;

//    pOutChar = lpNewRecorder + m_fileHeader.bfOffBits;
    nOutLen = (int)(RectWidth * RectHeight +
                 m_fileHeader.bfOffBits);
    pOutChar = lpNewRecorder;

    QFile file("test.bmp");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qWarning() << "Open file " << m_filePathName << " error";
        return false;
    }
    QDataStream out(&file);
    int nLen = (int)(RectWidth * RectHeight +
                      m_fileHeader.bfOffBits);
    int ret = out.writeRawData(lpNewRecorder,nLen);
    if( ret != nLen)
    {
        qWarning() << "Write error";
        file.close();
        return false;
    }

    file.close();
    delete[] m_pBuf;
    m_pBuf = nullptr;
    qDebug() <<"Save character successful";

//    m_iIsFinished = true;
    return true;
}

bool BMPFile::getCharactor(CharacterVector *pCharactor, const int maxSize)
{
    if( !start())
    {
        return false;
    }
    if(maxSize != CHARACTER_LENGTH)
    {
        qWarning() << "Charactor lenght not equal";
        return false;
    }
    memcpy((void*)pCharactor,m_pChara,sizeof(CharacterVector)*CHARACTER_LENGTH);
    return true;
}

void BMPFile::setGetAlgorithm(int index)
{
    m_getAlgorithmIndex = index;
}

void BMPFile::setDBAdapter(const database_type &pDB)
{
    m_pDB = pDB;
}

void BMPFile::setLastName(const QString &name)
{
    m_lastFileName = name;
}

void BMPFile::setRecogniseAlgorithm(int index)
{
    m_recoAlgorithmIndex = index;
}

bool BMPFile::stepExec(int index)
{
    if(m_mapStepFuncPtr.end() == m_mapStepFuncPtr.find(index))
    {
        qWarning() << "There is not function ptr of index " << index;
        return false;
    }
    m_curIndex = index;
    StepFuncPtr pFun = m_mapStepFuncPtr[index];
    return (this->*(pFun))();
}

void BMPFile::getRepoInfo(RepositoryInfo_t &repoInfo) const
{
    repoInfo = m_repositoryInfo;
}

void BMPFile::getSimilarity(double &d) const
{
    d = m_similarity;
}

bool BMPFile::stepFindInner()
{
    if( STEP_FIND_INNER_INDEX != m_curIndex)
    {
        qWarning() << "Step index error,should be " <<
                      STEP_FIND_INNER_INDEX;
        return false;
    }
    if(!m_iIsInitiliztion)
    {
        init();
    }

    if( !threshold() )
    {
        qWarning() << "error";
        return false;
    }

    //malloc
    const long lWidth = m_infoHeader.biWidth;
    const long lHeight = m_infoHeader.biHeight;
    m_recordSize = lWidth * lHeight;
    if(m_pRecorder)
    {
        delete[] m_pRecorder;
        m_pRecorder = nullptr;
    }
    m_pRecorder = new char[m_recordSize];
    if( nullptr == m_pRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)m_pRecorder,1,m_recordSize);
    if( !pupilContour(m_pRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    listPoint_type PointListForPHT;
    if( !findPHTPoint(m_pRecorder,PointListForPHT) )
    {
        qWarning() << "error";
        return false;
    }
    //check
    if(PointListForPHT.isEmpty())
    {
        qWarning() << "Not suppert picture or is too much mohu";
        return false;
    }

    if( !PHT(PointListForPHT,m_innerCircle) )
    {
        qWarning() << "error";
        return false;
    }

    //malloc temp to save as bmp
    char * pTemp = new char[m_bufSize];
    if( nullptr == pTemp)
    {
        qWarning() << "New error";
        return false;
    }
    memcpy(pTemp,m_pBuf,m_bufSize);

    if( !drainCircle(pTemp,m_innerCircle) )
    {
        qWarning() << "error";
        delete[] pTemp;
        return false;
    }

    if( !saveAsBmp(pTemp,(int)m_bufSize) )
    {
        qWarning() << "error";
        delete[] pTemp;
        return false;
    }
    delete[] pTemp;

    m_preIndex = m_curIndex;
    qDebug() << "Find inner successful";
    return true;
}

bool BMPFile::stepFindOuter()
{
    if( STEP_FIND_INNER_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_FIND_OUTER_INDEX;
        return false;
    }

    if( !findOuterCircle(m_innerCircle,m_outerCircle) )
    {
        qWarning() << "error";
        return false;
    }

    //malloc temp to save as bmp
    char * pTemp = new char[m_bufSize];
    if( nullptr == pTemp)
    {
        qWarning() << "New error";
        return false;
    }
    memcpy(pTemp,m_pBuf,m_bufSize);

    if( !drainCircle(pTemp,m_outerCircle) )
    {
        qWarning() << "error";
        delete[] pTemp;
        return false;
    }

    if( !saveAsBmp(pTemp,(int)m_bufSize) )
    {
        qWarning() << "error";
        delete[] pTemp;
        return false;
    }
    delete[] pTemp;

    m_preIndex = m_curIndex;
    qDebug() << "Find outer successful";
    return true;
}

bool BMPFile::stepDLInsAlgorithm()
{
    if( STEP_FIND_OUTER_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_DLInsAlgorithm_INDEX;
        return false;
    }

    //malloc
    if(m_pRecorder)
    {
        delete[] m_pRecorder;
        m_pRecorder = nullptr;
    }
    const long RectWidth =512;
    const long RectHeight = 128;
    m_recordSize = RectWidth * RectHeight +
            m_fileHeader.bfOffBits;
    m_pRecorder = new char[m_recordSize];
    if( nullptr == m_pRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)m_pRecorder,0,m_recordSize);
    memcpy((void*)m_pRecorder,
           (const void*)m_pBuf,
           m_fileHeader.bfOffBits);

    //update width and height
    char* pTemp = m_pRecorder;
    pTemp += 2;
    uint32* pUint32 = (uint32*)pTemp;
//    qDebug() << *pUint32;
    *pUint32 = m_recordSize;
    pTemp = m_pRecorder + BMP_FILE_HEADER_SIZE;
    pTemp += sizeof(m_infoHeader.biSize);
    pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth;
    ++pUint32;
    *pUint32 = RectHeight;

    pTemp = m_pRecorder + BMP_FILE_HEADER_SIZE + 20;
    pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth * RectHeight;

    if( !TurnToRect(m_innerCircle,m_outerCircle,m_pRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    if( !saveAsBmp(m_pRecorder,(int)m_recordSize) )
    {
        qWarning() << "error";
        return false;
    }
    m_preIndex = m_curIndex;
    qDebug() << "DLInsAlgorithm successful";
    return true;
}

bool BMPFile::stepLOGBin()
{
    if( STEP_DLInsAlgorithm_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_LOGBin_INDEX;
        return false;
    }

    LOGBin(m_pRecorder);

    if( !saveAsBmp(m_pRecorder,(int)m_recordSize) )
    {
        qWarning() << "error";
        return false;
    }
    m_preIndex = m_curIndex;
    qDebug() << "LOGBin successful";
    return true;
}

bool BMPFile::stepMorphological()
{
    if( STEP_LOGBin_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_Morphological_INDEX;
        return false;
    }

    Morphological(m_pRecorder);

    if( !saveAsBmp(m_pRecorder,(int)m_recordSize) )
    {
        qWarning() << "error";
        return false;
    }
    m_preIndex = m_curIndex;
    qDebug() << "Morphological successful";
    return true;
}

bool BMPFile::stepGetCharactor()
{
    if( STEP_Morphological_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_Get_Chara_INDEX;
        return false;
    }
    if( 0 == m_getAlgorithmIndex)
    {
        qWarning() << "Not set AlgorithmIndex";
        return false;
    }

    if( 1 == m_getAlgorithmIndex)
    {//PCA
        int tab = 0;
        PointInformation pointInfor[255];
        MarkthePoint(m_pRecorder, pointInfor, tab);
        GetCharacterVector(pointInfor, tab, m_pChara, CHARACTER_LENGTH);
    }
    else if( 2 == m_getAlgorithmIndex)
    {
        int tab = 0;
        PointInformation pointInfor[255];
        MarkthePoint(m_pRecorder, pointInfor, tab);
        GetCharacterVector(pointInfor, tab, m_pChara, CHARACTER_LENGTH);
    }

    m_getAlgorithmIndex = 0;
    m_preIndex = m_curIndex;
    qDebug() << "Get charactor successful";
    return true;
}

bool BMPFile::stepSaveCharactor()
{
    if( STEP_Get_Chara_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_Save_Chara_INDEX;
        return false;
    }

    if("" == m_lastFileName)
    {
        qWarning() << "Not set lastFileName";
        return false;
    }

    if(!saveCharaToDB())
    {
        m_lastFileName = "";
        return false;
    }

    m_lastFileName = "";
    m_preIndex = m_curIndex;
    qDebug() << "Save charactor successful";
    return true;
}

bool BMPFile::stepRecognise()
{
    if( STEP_Get_Chara_INDEX != m_preIndex &&
        STEP_Save_Chara_INDEX != m_preIndex)
    {
        qWarning() << "Step index error,pre step " << m_preIndex <<
                      ",but current step is " <<
                      STEP_Recognise_INDEX;
        return false;
    }
    if( 0 == m_recoAlgorithmIndex)
    {
        qWarning() << "Not set AlgorithmIndex";
        return false;
    }

    if( 1 == m_recoAlgorithmIndex)
    {//KNN
        //TODO:
        if( ! knnRecognise())
        {
            m_recoAlgorithmIndex = 0;
            return false;
        }
    }
    else if( 2 == m_recoAlgorithmIndex)
    {
        //TODO:
        if( ! knnRecognise())
        {
            m_recoAlgorithmIndex = 0;
            return false;
        }
    }

    m_recoAlgorithmIndex = 0;
    m_preIndex = m_curIndex;
    qDebug() << "Recognise successful";
    return true;
}

bool BMPFile::init()
{
    if(m_iIsInitiliztion)
    {
        return true;
    }
    try
    {
        //check file
        m_pFile.reset(new QFile(m_filePathName));
        if( ! m_pFile->exists())
        {
            qWarning() << "File " << m_filePathName << " is not exists";
            return false;
        }
        if(!m_pFile->open(QIODevice::ReadOnly))
        {
            qWarning() << "Open file " << m_filePathName << " error";
            return false;
        }
        if( MAX_FILE_SIZE < m_pFile->size())
        {
            qWarning() << "Size " << m_pFile->size()/1024/1024 <<
                          "MB but max is " << MAX_FILE_SIZE/1024/1024 << "MB";
            m_pFile->close();
            return false;
        }
        m_bufSize = m_pFile->size();

        //check if BMP
        if(!getFileHeader())
        {
            m_pFile->close();
            return false;
        }
        if( 0x4D42 != m_fileHeader.bfType)
        {//"BM" = 0x4D42
            qWarning() << "File is not BMP";
            m_pFile->close();
            return false;
        }
        qDebug() << "File " << m_filePathName <<
            " is BMP,and size" << m_fileHeader.bfSize <<
            ",offBtyes=" << m_fileHeader.bfOffBits;

        //check if 8 bpp
        if( ! getInfoHeader())
        {
            m_pFile->close();
            return false;
        }
        if( 8 != m_infoHeader.biBitCount)
        {
            qWarning() << "File is not 8 bpp";
            m_pFile->close();
            return false;
        }
        readBuf();
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        m_pFile->close();
        return false;
    }
    m_iIsInitiliztion = true;

//    qDebug() << "uint64:" << sizeof(uint64) <<
//                "uint32:" << sizeof(uint32);

    m_pFile->close();
    return true;
}

void BMPFile::initMap()
{
    m_mapStepFuncPtr.clear();

    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_FIND_INNER_INDEX,&BMPFile::stepFindInner));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_FIND_OUTER_INDEX,&BMPFile::stepFindOuter));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_DLInsAlgorithm_INDEX,&BMPFile::stepDLInsAlgorithm));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_LOGBin_INDEX,&BMPFile::stepLOGBin));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_Morphological_INDEX,&BMPFile::stepMorphological));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_Get_Chara_INDEX,&BMPFile::stepGetCharactor));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_Save_Chara_INDEX,&BMPFile::stepSaveCharactor));
    m_mapStepFuncPtr.insert(std::make_pair(
        STEP_Recognise_INDEX,&BMPFile::stepRecognise));

    qDebug() << "mapFunction size=" << m_mapStepFuncPtr.size();
}

void BMPFile::findMaxNum(CharacterVector *pCharactor, int maxSize)
{
    if( nullptr == pCharactor)
    {
        return;
    }
    //x
    CharacterVector* pTemp = pCharactor;
    long maxNum = pTemp->x;
    for(int index = 0; index<maxSize; ++index)
    {
        if( maxNum < pTemp->x)
        {
            maxNum = pTemp->x;
        }
        ++pTemp;
    }
    qDebug() << "Max x=" << maxNum;

    //y
    pTemp = pCharactor;
    maxNum = pTemp->y;
    for(int index = 0; index<maxSize; ++index)
    {
        if( maxNum < pTemp->y)
        {
            maxNum = pTemp->y;
        }
        ++pTemp;
    }
    qDebug() << "Max y=" << maxNum;

    return;
}

bool BMPFile::start()
{
    if( m_iIsFinished)
    {
        return true;
    }
    if(!m_iIsInitiliztion)
    {
        init();
    }
    //qiu huidu value
    if( !threshold() )
    {
        qWarning() << "error";
        return false;
    }

    //malloc
    const long lWidth = m_infoHeader.biWidth;
    const long lHeight = m_infoHeader.biHeight;
    char* lpRecorder = new char[
            m_infoHeader.biWidth *
            m_infoHeader.biHeight];
    if( nullptr == lpRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpRecorder,1,lHeight*lWidth);
    if( !pupilContour(lpRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    listPoint_type PointListForPHT;
    if( !findPHTPoint(lpRecorder,PointListForPHT) )
    {
        qWarning() << "error";
        return false;
    }
    //check
    if(PointListForPHT.isEmpty())
    {
        qWarning() << "Not suppert picture or is too much mohu";
        return false;
    }
    CIRCLE InnerCircle;
    if( !PHT(PointListForPHT,InnerCircle) )
    {
        qWarning() << "error";
        return false;
    }
    CIRCLE OuterCircle;
    if( !findOuterCircle(InnerCircle,OuterCircle) )
    {
        qWarning() << "error";
        return false;
    }
    //delete
    delete[] lpRecorder;
    lpRecorder = nullptr;

    const uint32 RectWidth=512;
    const uint32 RectHeight=128;
    char* lpNewRecorder = new char[
            RectWidth * RectHeight +
            m_fileHeader.bfOffBits];
    if( nullptr == lpNewRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpNewRecorder,0,
           RectWidth*RectHeight + m_fileHeader.bfOffBits);
    memcpy((void*)lpNewRecorder,
           (const void*)m_pBuf,
           m_fileHeader.bfOffBits);

    //update width and height
    char* pTemp = lpNewRecorder;
    pTemp += BMP_FILE_HEADER_SIZE;
    pTemp += sizeof(m_infoHeader.biSize);
    uint32* pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth;
    ++pUint32;
    *pUint32 = RectHeight;

    if( !TurnToRect(InnerCircle,OuterCircle,lpNewRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    LOGBin(lpNewRecorder);
    Morphological(lpNewRecorder);

    /*int tab = 0;
    PointInformation pointInfor[255];
    MarkthePoint(lpNewRecorder, pointInfor, tab);
    CharacterVector CharaV1[CHARACTER_LENGTH];
    GetCharacterVector(pointInfor, tab, CharaV1, CHARACTER_LENGTH);
    //存储特征向量
    FileName_Chara FileCharaV1;
    FileCharaV1.FileName = "source.txt";
    FileCharaV1.Chara = CharaV1;
    MySaveCharaV(FileCharaV1, CHARACTER_LENGTH);

    memcpy(m_pChara,CharaV1,sizeof(m_pChara));

    findMaxNum(m_pChara,CHARACTER_LENGTH);*/

//    m_hDIBTarget = lpNewRecorder;

    //delete[] lpNewRecorder;
    //lpNewRecorder = nullptr;

    delete[] m_pBuf;
    m_pBuf = nullptr;
    qDebug() <<"Save character successful";

    m_iIsFinished = true;
    return true;
}

void BMPFile::xiaoboguolv()
{
    int tab = 0;
    PointInformation pointInfor[255];
    MarkthePoint(lpNewRecorder, pointInfor, tab);
    CharacterVector CharaV1[CHARACTER_LENGTH];
    GetCharacterVector(pointInfor, tab, CharaV1, CHARACTER_LENGTH);
    /*//存储特征向量
    FileName_Chara FileCharaV1;
    FileCharaV1.FileName = "source.txt";
    FileCharaV1.Chara = CharaV1;
    MySaveCharaV(FileCharaV1, CHARACTER_LENGTH);*/

    memcpy(m_pChara,CharaV1,sizeof(m_pChara));

    findMaxNum(m_pChara,CHARACTER_LENGTH);

}

void BMPFile::pca()
{
    int tab = 0;
    PointInformation pointInfor[255];
    MarkthePoint(lpNewRecorder, pointInfor, tab);
    //尝试使用PCA
    double pcadata[128][7];
    for(int i=0;i<128;i++)
    {
        pcadata[i][0]=pointInfor[i].left;
        pcadata[i][1]=pointInfor[i].right;
        pcadata[i][2]=pointInfor[i].bottom;
        pcadata[i][3]=pointInfor[i].top;
        pcadata[i][4]=pointInfor[i].size;
        pcadata[i][5]=pointInfor[i].xsum;
        pcadata[i][6]=pointInfor[i].ysum;
    }
    int i,t;
    int m,n;
    double **x,**c,**v,**Project;
    double *A,*B;
    sourcedata pp;

    double eps=0.000001; //jacobi方法的终止精度
    double getratio=0.9; //特征值的提取率

    PCA  testpca(128,7);   //声明一个对象并初始化
    pp=testpca.getdata(pcadata);
    m=pp.m;
    n=pp.n;
    x=pp.data;

    A=new double[n];
    B=new double[n];
    v=new double*[n];
    for(i=0;i<n;i++)
        v[i]=new double[n];

    testpca.standarddata(x); //对数据进行标准化处理
    c=testpca.matrixproduct(x); //获取协方差矩阵
    i=testpca.jcb(c,v,eps,100); //求取特征值和特征向量
    for(int k=0;k<n;k++)
        A[k]=c[k][k]; //获取特征值
    testpca.zhengjiao(v);   //正交化特征向量
    testpca.selectionsort(A,v); //特征值和特征向量排序
    t=testpca.selectcharactor(A,getratio,B); //提取特征值

    if(t>=1&&t<=n)
        Project=testpca.getProject(t,x,v);  //计算投影

    CharacterVector CharaV1[CHARACTER_LENGTH];
    GetCharacterVector(pointInfor, tab, CharaV1, CHARACTER_LENGTH);
    //存储特征向量
    FileName_Chara FileCharaV1;
    FileCharaV1.FileName = "source.txt";
    FileCharaV1.Chara = CharaV1;
    MySaveCharaV(FileCharaV1, CHARACTER_LENGTH);

    memcpy(m_pChara,CharaV1,sizeof(m_pChara));

    findMaxNum(m_pChara,CHARACTER_LENGTH);

//    m_hDIBTarget = lpNewRecorder;

//    delete[] lpNewRecorder;
//  lpNewRecorder = nullptr;

//    delete[] m_pBuf;
//    m_pBuf = nullptr;
//    qDebug() <<"Save character successful";

//    m_iIsFinished = true;
//    return true;
}

void BMPFile::reset()
{
    m_getAlgorithmIndex = 0;
    m_recoAlgorithmIndex = 0;
    m_curIndex = 0;
    m_preIndex = 0;
    m_bufSize = 0;
    m_recordSize = 0;
    m_threshold = 0;
    m_iIsFinished = false;
    m_iIsInitiliztion = false;
    m_pBuf = nullptr;
    m_pRecorder = nullptr;

    m_lastFileName = "";

    initMap();
}

bool BMPFile::readBuf()
{
    if( 0 == m_bufSize)
    {
        qWarning() << "bufSize is 0";
        return false;
    }
    QFile file(m_filePathName);
    try
    {
        m_pBuf = new char[m_bufSize];
        if( nullptr == m_pBuf)
        {
            qWarning() << "New error";
            return false;
        }
        memset((void*)m_pBuf,0,m_bufSize);
//        QString temp = m_filePathName.replace(QRegExp("\\/"), "\\\\");
//        std::string strTemp = m_filePathName.toStdString();
//        const char* pChar = strTemp.c_str();
//        FILE* fp = fopen(m_filePathName.toStdString().c_str(),"rb");
//        if( nullptr == fp )
//        {
//            qWarning() << "open file error";
//            return false;
//        }
//        qint64 ret = fread(m_pBuf,1,m_bufSize,fp);
//        if( ret != m_bufSize)
//        {
//            qWarning() << "Read error";
//            return false;
//        }
//        fclose(fp);
        if(!file.open(QIODevice::ReadOnly))
        {
            qWarning() << "Open file " << m_filePathName << " error";
            return false;
        }
        QDataStream in(&file);
        int nLen = (uint)m_bufSize;
        int ret = in.readRawData(m_pBuf,nLen);
        if( ret != nLen)
        {
            qWarning() << "Read error";
            file.close();
            return false;
        }
//        int index = 10;
//        char ch = *(m_pBuf+index++);
//        ch = *(m_pBuf+index++);
//        index = 1078;
//        ch = *(m_pBuf+index++);
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        if(file.isOpen())
        {
            file.close();
        }
        return false;
    }

    file.close();
    return true;
}

bool BMPFile::getFileHeader()
{
    //check
    if( !m_pFile->isOpen())
    {
        qWarning() << "File is not open";
        return false;
    }
    try
    {
        if(!m_pFile->seek(0))
        {
            qWarning() << "Seek error";
            return false;
        }
        BMP_GET_HEADER(m_fileHeader.bfType);
        BMP_GET_HEADER(m_fileHeader.bfSize);
        BMP_GET_HEADER(m_fileHeader.bfReserved1);
        BMP_GET_HEADER(m_fileHeader.bfReserved2);
        BMP_GET_HEADER(m_fileHeader.bfOffBits);
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        return false;
    }
    return true;
}

bool BMPFile::getInfoHeader()
{
    //check
    if( !m_pFile->isOpen())
    {
        qWarning() << "File is not open";
        return false;
    }
    try
    {
        if(!m_pFile->seek(BMP_FILE_HEADER_SIZE))
        {
            qWarning() << "Seek error";
            return false;
        }
        BMP_GET_HEADER(m_infoHeader.biSize);
        BMP_GET_HEADER(m_infoHeader.biWidth);
        BMP_GET_HEADER(m_infoHeader.biHeight);
        BMP_GET_HEADER(m_infoHeader.biPlanes);
        BMP_GET_HEADER(m_infoHeader.biBitCount);
        BMP_GET_HEADER(m_infoHeader.biCompression);
        BMP_GET_HEADER(m_infoHeader.biSizeImage);
        BMP_GET_HEADER(m_infoHeader.biXPelsPerMeter);
        BMP_GET_HEADER(m_infoHeader.biYPelsPerMeter);
        BMP_GET_HEADER(m_infoHeader.biClrUsed);
        BMP_GET_HEADER(m_infoHeader.biClrImportant);
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        return false;
    }
    return true;
}

void BMPFile::getMinThreshold(char *pChar,
    int &minIndex, int& nThreshold)
{
    if( nullptr == pChar)
    {
        qWarning() << "nullptr";
        return;
    }
    char* pData = pChar + m_fileHeader.bfOffBits;
    const long nWidth = m_infoHeader.biWidth;
    const long nHeight = m_infoHeader.biHeight;
    long nLineBytes = WIDTHBYTES(m_infoHeader.biWidth*8);

    char* pTemp = nullptr;
    int arrThreshold[256];
    memset((void*)arrThreshold,0,sizeof(arrThreshold));
    for(int y = 0; y < nHeight; ++y)
    {
        for(int x = 0; x < nWidth; ++x)
        {
            pTemp = pData + y * nLineBytes + x;
            ++arrThreshold[*((unsigned char *)(pTemp))];
        }
    }

    //get min
    nThreshold = arrThreshold[0];
    minIndex = 0;
    for(int index = 1; index < 256; ++index)
    {
        if( nThreshold > arrThreshold[index])
        {
            nThreshold = arrThreshold[index];
            minIndex = index;
        }
    }
    return;
}

bool BMPFile::drainCircle(char *pChar, CIRCLE circle)
{
    if( nullptr == pChar)
    {
        qWarning() << "nullptr";
        return false;
    }
    char* pData = pChar + m_fileHeader.bfOffBits;
    const long nWidth = m_infoHeader.biWidth;
    const long nHeight = m_infoHeader.biHeight;
    long nLineBytes = WIDTHBYTES(m_infoHeader.biWidth*8);

    long yMin = circle.y - circle.r;
    long yMax = circle.y + circle.r;
    long xMin = circle.x - circle.r;
    long xMax = circle.x + circle.r;

    char* pTemp = nullptr;

    int minIndex = 0;
    int minThreshold;
    getMinThreshold(pChar,minIndex,minThreshold);
    qDebug() << "Index " << minIndex <<
                " min threshold=" << minThreshold;
    unsigned char ch = 255;
    if( 10 > minThreshold)
    {
        pTemp = pChar + 54;
        RGBQUAD* pRgbQuad = (RGBQUAD*)pTemp;
        pRgbQuad += minIndex;
        pRgbQuad->rgbRed = 255;
        pRgbQuad->rgbGreen = 0;
        pRgbQuad->rgbBlue = 0;
        ch = (uint8)minIndex;
    }

    //check
    if( 0 > yMin )
    {
        yMin = 0;
    }
    if( 0 > xMin )
    {
        xMin = 0;
    }
    if( nWidth < xMax)
    {
        xMax = nWidth;
    }
    if( nHeight < yMax)
    {
        yMax = nHeight;
    }
    if( nWidth < xMin ||
            nHeight < yMin ||
            0 > yMax ||
            0 > xMax)
    {
        qWarning() << "error";
        return false;
    }

    //from yMin to yMax
    //min y point,only one
    pTemp = pData + yMin * nLineBytes + xMin;
    *pTemp = ch;
    for(long y = yMin + 1; y < yMax - 1; ++y)
    {
        double d = pow(circle.r,2) - pow(y-circle.y,2);
        d = sqrt(d);
        long nTemp = d/1;
        long x1 = circle.x - nTemp;
        long x2 = circle.x + nTemp;
        //check
        if( 0 < x1 && nWidth > x1)
        {
            pTemp = pData + y * nLineBytes + x1;
            *pTemp = ch;
        }
        if( 0 < x2 && nWidth > x2)
        {
            pTemp = pData + y * nLineBytes + x2;
            *pTemp = ch;
        }
    }

    //max y point,only one
    pTemp = pData + yMax * nLineBytes + xMax;
    *pTemp = ch;

    //from xMin to xMax
    //min x point only one
    pTemp = pData + circle.y * nLineBytes + xMin;
    *pTemp = ch;
    for(long x = xMin + 1; x < xMax - 1; ++x)
    {
        double d = pow(circle.r,2) - pow(x-circle.x,2);
        d = sqrt(d);
        long nTemp = d/1;
        long n1 = circle.y - nTemp;
        long n2 = circle.y + nTemp;
        //check
        if( 0 < n1 && nHeight > n1)
        {
            pTemp = pData + n1 * nLineBytes + x;
            *pTemp = ch;
        }
        if( 0 < n2 && nHeight > n2)
        {
            pTemp = pData + n2 * nLineBytes + x;
            *pTemp = ch;
        }
    }
    //max x point only one
    pTemp = pData + circle.y * nLineBytes + xMax;
    *pTemp = ch;

    return true;
}

bool BMPFile::saveAsBmp(char *pChar, int nSize)
{
    if( nullptr == pChar )
    {
        qWarning() << "nullptr";
        return false;
    }
    QFile file("temp.bmp");
    if(!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
    {
        qWarning() << "Open file " << m_filePathName << " error";
        return false;
    }
    QDataStream out(&file);
    int ret = out.writeRawData(pChar,nSize);
    if( ret != nSize)
    {
        qWarning() << "Write error";
        file.close();
        return false;
    }

    file.close();
    return true;
}

bool BMPFile::saveCharaToDB()
{
    if( nullptr == m_pDB.data())
    {
        m_pDB.reset(new DataBase());
        if( ! m_pDB->createConnection())
        {
            qWarning() << "Create Connect DB Failed";
            return false;
        }
    }
    if( ! m_pDB->createConnection())
    {
        qWarning() << "Create Connect DB Failed";
        return false;
    }
    if( ! m_pDB->insertCharacotr(m_lastFileName,m_pChara,CHARACTER_LENGTH))
    {
        qWarning() << "Insert into DB Failed";
        return false;
    }
    m_pDB->printCount(TABLE_REPOSITORY_INFO);
    m_pDB->printCount(TABLE_CHARACTOR_RECORD);

    return true;
}

bool BMPFile::knnRecognise()
{
    //get repository info
    RepositoryInfo_t arrRepository[CHARACTER_LENGTH];
    if( nullptr == m_pDB.data())
    {
        m_pDB.reset(new DataBase());
        if( ! m_pDB->createConnection())
        {
            qWarning() << "Create Connect DB Failed";
            return false;
        }
    }
    if( ! m_pDB->createConnection())
    {
        qWarning() << "Create Connect DB Failed";
        return false;
    }

    int nSize = 0;
    if( ! m_pDB->queryRepository(arrRepository,nSize,CHARACTER_LENGTH))
    {
        qWarning() << "Query DB Failed";
        return false;
    }
    if( 0 == nSize)
    {
        qWarning() << "Size is 0";
        return false;
    }

//    BMPFile bmpLeftFile (m_rootPath + "/" +m_leftPictureName);
    double similarity = 0;
    double maxSimilarity = 0;
    int maxIndex = 0;

    CharacterVector arrCharactor[CHARACTER_LENGTH];
    int nCharaSize = 0;
    //compare first to update maxSimilarity
    if( ! m_pDB->queryCharactor(arrRepository[0].id,arrCharactor,nCharaSize,CHARACTER_LENGTH))
    {
        qWarning() << "Query DB Failed";
        return false;
    }
    if( CHARACTER_LENGTH != nCharaSize)
    {
        qWarning() << "Size of charactor is " << nCharaSize;
        return false;
    }
    qDebug() << "Will compare bmp " << arrRepository[0].uri;
    maxSimilarity = Compare(m_pChara,CHARACTER_LENGTH,
                    arrCharactor,CHARACTER_LENGTH);

    //compare least
    for(int index = 1;index<nSize;++index)
    {
        memset((void*)arrCharactor,0,sizeof(arrCharactor));
        if( ! m_pDB->queryCharactor(arrRepository[index].id,arrCharactor,nCharaSize,CHARACTER_LENGTH))
        {
            qWarning() << "Query DB Failed";
            return false;
        }
        if( CHARACTER_LENGTH != nCharaSize)
        {
            qWarning() << "Size of charactor is " << nCharaSize;
            return false;
        }
        qDebug() << "Will compare bmp " << arrRepository[index].uri;
        similarity = Compare(m_pChara,CHARACTER_LENGTH,
                        arrCharactor,CHARACTER_LENGTH);
        if( maxSimilarity < similarity)
        {
            maxSimilarity = similarity;
            maxIndex = index;
        }
    }//end for

    qDebug() << "Index " << maxIndex << " name " <<
            arrRepository[maxIndex].uri << " similarity "
            << maxSimilarity*100 << "%";
    //save result
    m_repositoryInfo = arrRepository[maxIndex];
    m_similarity = maxSimilarity;

    return true;
}

bool BMPFile::binarization()
{
    if(!m_iIsInitiliztion)
    {
        init();
    }

    if( !threshold() )
    {
        qWarning() << "error";
        return false;
    }

    //malloc
    const long lWidth = m_infoHeader.biWidth;
    const long lHeight = m_infoHeader.biHeight;
    char* lpRecorder = new char[
            m_infoHeader.biWidth *
            m_infoHeader.biHeight];
    if( nullptr == lpRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpRecorder,1,lHeight*lWidth);
    if( !pupilContour(lpRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    listPoint_type PointListForPHT;
    if( !findPHTPoint(lpRecorder,PointListForPHT) )
    {
        qWarning() << "error";
        return false;
    }
    //check
    if(PointListForPHT.isEmpty())
    {
        qWarning() << "Not suppert picture or is too much mohu";
        return false;
    }
    CIRCLE InnerCircle;
    if( !PHT(PointListForPHT,InnerCircle) )
    {
        qWarning() << "error";
        return false;
    }
    CIRCLE OuterCircle;
    if( !findOuterCircle(InnerCircle,OuterCircle) )
    {
        qWarning() << "error";
        return false;
    }
    //delete
    delete[] lpRecorder;
    lpRecorder = nullptr;

    //TODO:tomorrow finish
    const uint32 RectWidth=512;
    const uint32 RectHeight=128;
    char* lpNewRecorder = new char[
            RectWidth * RectHeight +
            m_fileHeader.bfOffBits];
    if( nullptr == lpNewRecorder)
    {
        qWarning() << "New error";
        return false;
    }
    memset((void*)lpNewRecorder,0,
           RectWidth*RectHeight + m_fileHeader.bfOffBits);
    memcpy((void*)lpNewRecorder,
           (const void*)m_pBuf,
           m_fileHeader.bfOffBits);

    //update width and height
    char* pTemp = lpNewRecorder;
    pTemp += BMP_FILE_HEADER_SIZE;
    pTemp += sizeof(m_infoHeader.biSize);
    uint32* pUint32 = (uint32*)pTemp;
    *pUint32 = RectWidth;
    ++pUint32;
    *pUint32 = RectHeight;

    if( !TurnToRect(InnerCircle,OuterCircle,lpNewRecorder) )
    {
        qWarning() << "error";
        return false;
    }

    LOGBin(lpNewRecorder);
    Morphological(lpNewRecorder);

//    m_hDIBTarget = lpNewRecorder;

    delete[] lpNewRecorder;
    lpNewRecorder = nullptr;

    qDebug() <<"Save character successful";

    return true;
}

bool BMPFile::threshold()
{
    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    long lWidth = m_infoHeader.biWidth;
    long lHeight = m_infoHeader.biHeight;
    long Count[BMP_MAX_COLOR_NUM] = {0};
    long lLineBytes = WIDTHBYTES(lWidth*8);

    LPSTR  lpSrc;
    long i;
    for(i=0;i<lHeight;i++)
    {
        for(long j=0;j<lWidth;j ++)
        {
            lpSrc=lpDIBBits+lLineBytes*i+j;
            Count[*((unsigned char *)(lpSrc))]+=1;
        }
    }
    Count[0]=0;
    Count[1]=(Count[1]+Count[0])/2;
    for(i=3;i<255;i++)
    {
        Count[i]=(Count[i]+Count[i-1]+Count[i+1])/3;
    }
    long difference[256];
    difference[0]=0;
    for(int i=1;i<256;i++)
        difference[i]=Count[i]-Count[i-1];
    unsigned char  threshold=0;
    long max=Count[0];
    for(int i=1;i<256;i++)
    {
        if(max<Count[i])
            max=Count[i];
        if((difference[i]<0)&&(difference[i+1]>=0)&&(max/2>Count[i+1])&&max>200)
        {
            threshold=(unsigned char)i+1;
            break;
        }
     }
    m_threshold = threshold;
    return true;
}

//tong kong nei bu lun kuo chu li
bool BMPFile::pupilContour(char* lpRecorder)
{
    long lLineBytes = WIDTHBYTES(m_infoHeader.biWidth*8);
    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    char* lpSrc = nullptr;
    uint8 threshold = m_threshold;
    try
    {
        for(uint32 i= 1;i<m_infoHeader.biHeight -1;i++)
        {
            for(uint32 j= 1;j<m_infoHeader.biWidth -1;j++)
            {
                lpSrc=lpDIBBits+lLineBytes*i+j;
                LPSTR lpSrc_right=lpDIBBits+lLineBytes*i+j+1;
                LPSTR lpSrc_left=lpDIBBits+lLineBytes*i+j-1;
                LPSTR lpSrc_top=lpDIBBits+lLineBytes*(i+1)+j;
                LPSTR lpSrc_bottom=lpDIBBits+lLineBytes*(i-1)+j;
                if(unsigned char (*lpSrc)<threshold)
                {
                    if(!((unsigned char (*lpSrc_right)<threshold)&&(unsigned char(*lpSrc_left)<threshold)
                        &&(unsigned char(*lpSrc_top)<threshold)&&(unsigned char(*lpSrc_bottom)<threshold)))
                            *(lpRecorder+lLineBytes*i+j)=0;
                }
            }
        }
        for(uint32 i=1;i<m_infoHeader.biHeight-1;i++)
        {
            for(uint32 j=1;j<m_infoHeader.biWidth-1;j++)
            {
                lpSrc=lpRecorder+lLineBytes*i+j;
                if(*lpSrc==(unsigned char)0)
                {
                    char a1=*(lpRecorder+lLineBytes*i+j+1);
                    char a2=*(lpRecorder+lLineBytes*i+j-1);
                    char a3=*(lpRecorder+lLineBytes*(i+1)+j);
                    char a4=*(lpRecorder+lLineBytes*(i+1)+j-1);
                    char a5=*(lpRecorder+lLineBytes*(i+1)+j+1);
                    char a6=*(lpRecorder+lLineBytes*(i-1)+j-1);
                    char a8=*(lpRecorder+lLineBytes*(i-1)+j);
                    char a7=*(lpRecorder+lLineBytes*(i-1)+j+1);
                    unsigned char a=a1+a2+a3+a4+a5+a6+a7+a8;
                    if(a>6)
                        *(lpRecorder+lLineBytes*i+j)=1;
                }
             }

        }
        for(uint32 i=m_infoHeader.biHeight-2;i>0;i--)
        {
             for(uint32 j=m_infoHeader.biWidth-2;j>0;j--)
             {
                lpSrc=lpRecorder+lLineBytes*i+j;
                if(*lpSrc==0)
                {
                    char a1=*(lpRecorder+lLineBytes*i+j+1);
                    char a2=*(lpRecorder+lLineBytes*i+j-1);
                    char a3=*(lpRecorder+lLineBytes*(i+1)+j);
                    char a4=*(lpRecorder+lLineBytes*(i+1)+j-1);
                    char a5=*(lpRecorder+lLineBytes*(i+1)+j+1);
                    char a6=*(lpRecorder+lLineBytes*(i-1)+j-1);
                    char a7=*(lpRecorder+lLineBytes*(i-1)+j+1);
                    char a8=*(lpRecorder+lLineBytes*(i-1)+j);
                    unsigned char a=a1+a2+a3+a4+a5+a6+a7+a8;
                    if(a>6)
                        *lpSrc=(unsigned char)1;
                }
             }
        }
    }
    catch(QException& ex)
    {
        qWarning() << ex.what();
        return false;
    }
    return true;
}

bool BMPFile::findPHTPoint(LPSTR lpRecorder, listPoint_type& PHTlist)
{
    long lHeight = m_infoHeader.biHeight;
    long lWidth = m_infoHeader.biWidth;
    LPSTR SourceImage = lpRecorder;

    bool bFindPoint;
    bool MeetTheEndOfLine;
    bool bFindStartPoint;
    CPoint StartPoint,CurrentPoint;

    int Direction[8][2]={{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0}};
    int BeginDirect;
//    LPSTR SourceImage=(char *)::GlobalLock(hSourceImage);
//    ::GlobalUnlock(hSourceImage);
    int LineNumber=0;
    for(long j=1;j<lHeight-1;j++)
    {
        for(long i=1;i<lWidth-1;i++)
        {
            bFindStartPoint=false;
            MeetTheEndOfLine=false;
            long PointNumberOfThisType=0;
            if(*((unsigned char *)(SourceImage+lWidth*j+i))==0)
            {
               StartPoint=CPoint(i,j);

               BeginDirect=0;

               CurrentPoint.x=StartPoint.x;
               CurrentPoint.y=StartPoint.y;
               PHTPoint PhtPoint;
               PhtPoint.Point=StartPoint;
               PhtPoint.LineNumber=LineNumber;
               PHTlist.push_back(PhtPoint);
               PointNumberOfThisType=1;
               int pixel_length=0;
               while(!MeetTheEndOfLine&&!bFindStartPoint)
               {
                    bFindPoint=false;
                    int TurnNumber=0;

                    while(!bFindPoint)
                    {
                        unsigned char a=*(SourceImage+(CurrentPoint.y+
                            Direction[BeginDirect][1])*lWidth+CurrentPoint.x+Direction[BeginDirect][0]);
                        if((CurrentPoint.y + Direction[BeginDirect][1]==StartPoint.y)&&(CurrentPoint.x
                            +Direction[BeginDirect][0]== StartPoint.x))
                        {
                            bFindStartPoint=true;
                            CurrentPoint.x=0;
                            CurrentPoint.y=0;
                            LineNumber++;
                            break;
                        }
                        if(a==0)
                        {
                            pixel_length++;
                            if(pixel_length==distant_used_for_PHT)
                            {
                                pixel_length=0;
                                PhtPoint.Point=CurrentPoint;
                                PhtPoint.LineNumber=LineNumber;
                                PHTlist.push_back(PhtPoint);
                                PointNumberOfThisType++;
                            }
                            bFindPoint = true;
                            *(SourceImage+(CurrentPoint.y)*lWidth+CurrentPoint.x)=1;
                            CurrentPoint.y=CurrentPoint.y+Direction[BeginDirect][1];
                            CurrentPoint.x=CurrentPoint.x+Direction[BeginDirect][0];
                            BeginDirect--;
                            if(BeginDirect==-1)
                                BeginDirect=7;
                            BeginDirect--;
                            if(BeginDirect==-1)
                                BeginDirect=7;
                        }
                        else
                        {
                            BeginDirect++;
                            if(BeginDirect==8)
                                BeginDirect=0;
                            TurnNumber++;
                            if(TurnNumber==8)
                            {
                                MeetTheEndOfLine=true;
                                LineNumber+=1;
                                *(SourceImage+(CurrentPoint.y)*lWidth+CurrentPoint.x)=1;
                                bFindPoint=true;
                            }

                        }
                    }//while(!bFindPoint)
                }//while(!MeetTheEndOfLine&&!bFindStartPoint)
                if(MeetTheEndOfLine||PointNumberOfThisType<4)
                {
                    for(i=0;i<PointNumberOfThisType;i++)
                        PHTlist.pop_back();
                    LineNumber--;
                }
            }//if
        }//for
    }//for
    return true;
}

bool BMPFile::PHT(listPoint_type &PHTlist,CIRCLE& outCircle)
{
    int a=PHTlist.size();
    listPointGroup_type PHTGroupList;
    int pos = 0;
    int pos_begin = 0;
    int pos_end = PHTlist.size();
//    POSITION pos=PHTlist->GetHeadPosition();
//    POSITION pos_begin=pos;
//    POSITION pos_end;
    PHTPoint point=PHTlist.at(pos++);
    PHTPointGROUP PHTGroup;
    int UsefulPointNumber=1;
    int LineNumber=point.LineNumber;
    bool FinishCircle=false;
    while(!FinishCircle)
    {
        bool MeetTheEnd=false;
        do
        {
            point=PHTlist.at(pos++);
            UsefulPointNumber++;
            if(0 > pos ||
                PHTlist.size() <= pos)
            {
                MeetTheEnd=true;
                FinishCircle=true;
            }
            else
            {
                if(point.LineNumber!=LineNumber)
                {
                    LineNumber=point.LineNumber;
                    MeetTheEnd=true;
                    UsefulPointNumber--;
                    --pos;
                    if(0 > pos)
                    {
                        pos = 0;
                    }
//                    PHTlist->GetPrev(pos);
                }
            }//else
        }while(!MeetTheEnd);

        pos_end=pos;
        int Step=UsefulPointNumber/3;
        pos=pos_begin;
        for(int i=0;i<UsefulPointNumber;i++)
        {
            PHTPoint point;
            point=PHTlist.at(pos++);
        }//equ pos=UsefulPointNumber;
        int i;
        for(i=0;i<UsefulPointNumber;i++)
        {
            PHTPoint point;
            point=PHTlist.at(pos_begin);
            pos=pos_begin;
            for(int j=0;j<i;j++)
                point=PHTlist.at(pos++);
            PHTGroup.a=point.Point;
            for(int j=0;j<Step;j++)
            {
                point=PHTlist.at(pos++);
                if( 0> pos ||
                    pos >= pos_end)
                    pos=pos_begin;
            }

            PHTGroup.b=point.Point;
            for(int j=0;j<Step;j++)
            {
                point=PHTlist.at(pos++);
                if( 0> pos ||
                    pos >= pos_end)
                    pos=pos_begin;
            }
            PHTGroup.c=point.Point;
            PHTGroupList.push_back(PHTGroup);
        }
        UsefulPointNumber=1;
        pos=pos_end;
    }//while(!FinishCircle)
//    pos=PHTGroupList.GetHeadPosition();
    pos = 0;
    a=PHTGroupList.size();
    QList<CIRCLE> circle;
//    CArray<CIRCLE,CIRCLE&> circle;
//    circle.reserve(a);
    for(int index = 0;index<a;++index)
    {
        circle.push_back(CIRCLE());
    }
    int CircleNumber=0;
    while( a > pos)
    {
        PHTPointGROUP PHTGroup=PHTGroupList.at(pos++);
        if((PHTGroup.a.y-PHTGroup.b.y)==0||(PHTGroup.b.y-PHTGroup.c.y)==0)
            continue;
        float k1=-(float)(PHTGroup.a.x-PHTGroup.b.x)/(float)(PHTGroup.a.y-PHTGroup.b.y);
        float k2=-(float)(PHTGroup.b.x-PHTGroup.c.x)/(float)(PHTGroup.b.y-PHTGroup.c.y);
        float d1=((PHTGroup.a.y+PHTGroup.b.y)-k1*(PHTGroup.a.x+PHTGroup.b.x))/2.0;
        float d2=((PHTGroup.b.y+PHTGroup.c.y)-k2*(PHTGroup.b.x+PHTGroup.c.x))/2.0;
        if(k1==k2)
            continue;
        float ac=-(d1-d2)/(k1-k2);
        float bc=k1*ac+d1;
        float  rc=sqrt(pow((PHTGroup.a.x-ac),2)+pow((PHTGroup.a.y-bc),2));
        circle[CircleNumber].x=(int)(ac+0.5);
        circle[CircleNumber].y=(int)(bc+0.5);
        circle[CircleNumber].r=(int)(rc+0.5);
        CircleNumber++;
    }//while
    QList<int> pointsum;
//    pointsum.SetSize(CircleNumber);
//    pointsum.reserve(CircleNumber);
    for(int index = 0;index<CircleNumber;++index)
    {
        pointsum.push_back(0);
    }
    int i;
    for(i=0;i<CircleNumber;i++)
        pointsum[i]=0;
    for(i=0;i<CircleNumber;i++)
    {
        for (int j=0;j<CircleNumber;j++)
        {
            if(distance(circle[i],circle[j])<2.5)
                pointsum[i]+=1;
        }
    }
    int max=0;
    for(i=1;i<CircleNumber;i++)
    {
        if (pointsum[i-1]<pointsum[i])
            max=i;
    }
    CIRCLE MaxCircle;
    MaxCircle.x=0;
    MaxCircle.y=0;
    MaxCircle.r=0;
    int counter=0;
    for(i=max;i<CircleNumber;i++)
    {
        if(pointsum[i]==pointsum[max])
        {
            MaxCircle.x+=circle[i].x;
            MaxCircle.y+=circle[i].y;
            MaxCircle.r+=circle[i].r;
            counter++;
        }
    }
    MaxCircle.x=(float)MaxCircle.x/(float)counter+0.5;
    MaxCircle.y=(float)MaxCircle.y/(float)counter+0.5;
    MaxCircle.r=(float)MaxCircle.r/(float)counter+0.5;
//    return MaxCircle;
    outCircle = MaxCircle;

    return true;
}

bool BMPFile::findOuterCircle(CIRCLE InnerCircle, CIRCLE &outCircle)
{
    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    long lWidth = (int)m_infoHeader.biWidth;
    long lHeight = (int)m_infoHeader.biHeight;
    long lLineBytes = WIDTHBYTES(m_infoHeader.biWidth*8);

    CIRCLE MaxCircle,MaxCircle1;

    MaxCircle.r=0;
    MaxCircle.x=0;
    MaxCircle.y=0;

    MaxCircle1.x=0;
    MaxCircle1.y=0;
    MaxCircle1.r=0;
    float max=0;

//    LONG lLineBytes;
    const int r_step=4;
    const int angle_step=1;
    const int centre_range=5;

//    lLineBytes=WIDTHBYTES(lWidth*8);
    for(int l=-centre_range;l<=centre_range;l++)
    {
        for(int k=-centre_range;k<=centre_range;k++)
        {
            int from=InnerCircle.r+4*centre_range;
            int to=min(from+5*InnerCircle.r,min(InnerCircle.x+k,lWidth-InnerCircle.x-k));
            int Array_Number=(to-from)/r_step;
            float * array_for_circle_integration=new float[Array_Number];
            float * convolution=new float[Array_Number];
            for(long m=0;m<Array_Number;m++)
            {
                array_for_circle_integration[m]=0;
                convolution[m]=0;
            }
            for(long r=from;r<to-r_step;r=r+r_step)
            {
                int sum_number=0;
                for(int i=-r_step/2;i<r_step/2;i++)
                {
                    for(float angle=30;angle>-30;angle=angle-angle_step)
                    {
                        if(InnerCircle.y+l+(long)((r+i)*sin(angle/360*2*pi))<0||
                            InnerCircle.y+l+(long)((r+i)*sin(angle/360*2*pi))>lHeight)
                            continue;
                        unsigned char w=(unsigned char)*(lpDIBBits+(InnerCircle.y+l+
                            (long)((r+i)*sin(angle/360*2*pi)))*lLineBytes+k+InnerCircle.x+
                            (long)((r+i)*cos(angle/360*2*pi)));
                        array_for_circle_integration[(r-from)/r_step]+=w;
                        sum_number++;
                    }
                }
                for(int i=-r_step/2;i<r_step/2;i++)
                {
                    for(float angle=150;angle<210;angle=angle+angle_step)
                    {
                        if(InnerCircle.y+l+(long)((r+i)*sin(angle/360*2*pi))<0||
                            InnerCircle.y+l+(long)((r+i)*sin(angle/360*2*pi))>lHeight)
                            continue;
                        array_for_circle_integration[(r-from)/r_step]+=(unsigned char)*(lpDIBBits+
                            (InnerCircle.y+l+(long)((r+i)*sin(angle/360*2*pi)))*lLineBytes+k+
                            InnerCircle.x+(long)((r+i)*cos(angle/360*2*pi)));
                        sum_number++;
                    }
                }
                array_for_circle_integration[(r-from)/r_step]=
                        array_for_circle_integration[(r-from)/r_step]/sum_number;
             }
            convolution[0]=(8*array_for_circle_integration[0]+array_for_circle_integration[1])/9.0;
            for(long r=from+r_step;r<to-2*r_step;r=r+r_step)
            {
                convolution[(r-from)/r_step]=(8*array_for_circle_integration[(r-from)/r_step]
                +array_for_circle_integration[(r-from-r_step)/r_step]+
                 array_for_circle_integration[(r-from+r_step)/r_step])/10.0;
            }
            convolution[(to-r_step-from)/r_step]=(8*array_for_circle_integration[(to-r_step-from)/r_step]
                +array_for_circle_integration[(to-2*r_step-from)/r_step])/9.0;
             for(long i=1;i<(to-from-r_step)/r_step;i++)
             {
                float a=convolution[i]-convolution[i-1];
                if(a>max)
                {
                    max=a;
                    MaxCircle1.r=from+(i-1)*r_step;
                    MaxCircle1.x=InnerCircle.x+k;
                    MaxCircle1.y=InnerCircle.y+l;
                }
            }
         delete[] array_for_circle_integration;
         delete[] convolution;
        }//for
    }//for
    //return MaxCircle1;

    long * TheMax=new long[r_step];
    int sum_number=0;
    int i=0;
    for(long  r=MaxCircle1.r-r_step/2+1;r<MaxCircle1.r+r_step/2;r++)
    {
        for(float angle=30;angle>-30;angle=angle-angle_step)
        {
            if(MaxCircle1.y+(long)(r*sin(angle/360*2*pi))<0||
                MaxCircle1.y+(long)(r*sin(angle/360*2*pi))>lHeight)
                    continue;
            TheMax[i]+=*(lpDIBBits+(MaxCircle1.y+(long)(r*sin(angle/360*2*pi)))*lLineBytes+
                MaxCircle1.x+(long)(r*cos(angle/360*2*pi)));
            sum_number++;
        }
        for(float angle=150;angle<210;angle=angle+angle_step)
        {
            if(MaxCircle1.y+(long)(r*sin(angle/360*2*pi))<0||
                MaxCircle1.y+(long)(r*sin(angle/360*2*pi))>lHeight)
                    continue;
            TheMax[i]+=*(lpDIBBits+(MaxCircle1.y+(long)(r*sin(angle/360*2*pi)))*lLineBytes+
                MaxCircle1.x+(long)(r*cos(angle/360*2*pi)));
            sum_number++;
        }
        TheMax[i]=TheMax[i]/sum_number;
        i++;
    }
    long differ=0;
    for(int j=1;j<=i;j++)
    {
        if(abs(TheMax[j]-TheMax[j-1])>differ)
        {
            differ=TheMax[j]-TheMax[j-1];
            MaxCircle.x=MaxCircle1.x;
            MaxCircle.y=MaxCircle1.y;
            MaxCircle.r=MaxCircle1.r-r_step/2+1+j;
        }
    }
    delete[] TheMax;
//    return MaxCircle;
    outCircle = MaxCircle;
    return true;
}

bool BMPFile::TurnToRect(CIRCLE Inner,CIRCLE Outer,LPSTR pNewPtr)
{
//    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
//    long lWidth = m_infoHeader.biWidth;
//    long lHeight = m_infoHeader.biHeight;
//    uint32 lLineBytes = WIDTHBYTES(lWidth*8);

    const long RectWidth=512;
    const long RectHeight=128;
    char* lpNewDIBBits = pNewPtr + m_fileHeader.bfOffBits;
    long lNewLineBytes = WIDTHBYTES(RectWidth*8);

    LPSTR lpDst;
    float i,j;
    float i0,j0;

    if(Inner.x==Outer.x)
    {
        for (i=0.0;i<RectWidth;i++)
        {
            int x1=Inner.x+Inner.r*cos((i/(RectWidth-1))*2*pi);
            int y1=Inner.y+Inner.r*sin((i/(RectWidth-1))*2*pi);
            float r0=sqrt(pow((double)(Inner.x-Outer.x),2)+pow((double)(Inner.y-Outer.y),2));
            float q1;
            float fTemp = i/RectWidth;
            if(i/RectWidth<=1/4)
                q1=(i/RectWidth)*2*pi+pi/2;
            else if(1/4 < fTemp &&
                    fTemp <= 1/2)
                q1=pi-(i/RectWidth)*2*pi+pi/2;
            else if(1/2 < fTemp &&
                    fTemp <= 3/4)
                q1=3/2*pi-(i/RectWidth)*2*pi;
            else
                q1=(i/RectWidth)*2*pi-pi   ;
            float q2=asin((r0*sin(q1))/Outer.r);
            float Ia=sqrt(pow((double)r0,2)+pow((double)Outer.r,2)-2*r0*Outer.r*cos(pi-q1-q2));
            int x2=Inner.x+Ia*cos((i/(RectWidth-1))*2*pi);
            int y2=Inner.y+Ia*sin((i/(RectWidth-1))*2*pi);
            for(j=0.0;j<RectHeight;j++)
            {
                float lamuda=j/(RectHeight-1);
                i0=(1-lamuda)*x1+lamuda*x2;
                j0=(1-lamuda)*y1+lamuda*y2;
                lpDst=lpNewDIBBits+lNewLineBytes*((long)j)+(long)i;
                *lpDst=DLInsAlgorithm(i0,j0);
            }
        }
    }
    if(Inner.x<Outer.x&&Inner.y>=Outer.y)
    {
        for (i=0.0;i<RectWidth;i++)
        {
            int x1=Inner.x+Inner.r*cos((i/(RectWidth-1))*2*pi);
            int y1=Inner.y+Inner.r*sin((i/(RectWidth-1))*2*pi);
            float q1=atan((double)abs((Inner.y-Outer.y)/(Inner.x-Outer.x)));
            float r0=sqrt(pow((double)(Inner.x-Outer.x),2)+pow((double)(Inner.y-Outer.y),2));
            float q=(i/(RectWidth-1))*2*pi+q1;
            if(q>pi)
                q=2*pi-q;
            if(q<0)
            q=-q;
            float q2=asin(r0*sin(q)/Outer.r);
            float Ia=sqrt(pow((double)r0,2)+pow((double)Outer.r,2)-2*r0*Outer.r*cos(pi-q-q2));
            int x2=Inner.x+Ia*cos((i/(RectWidth-1))*2*pi);
            int y2=Inner.y+Ia*sin((i/(RectWidth-1))*2*pi);
            for(j=0.0;j<RectHeight;j++)
            {
                float lamuda=j/(RectHeight-1);
                i0=(1-lamuda)*x1+lamuda*x2;
                j0=(1-lamuda)*y1+lamuda*y2;
                lpDst=lpNewDIBBits+lNewLineBytes*((long)j)+(long)i;
                *lpDst=DLInsAlgorithm(i0,j0);
            }
        }
    }
    if(Inner.x>Outer.x&&Inner.y>=Outer.y)
    {
        for (i=0.0;i<RectWidth;i++)
        {
            int x1=Inner.x+Inner.r*cos((i/(RectWidth-1))*2*pi);
            int y1=Inner.y+Inner.r*sin((i/(RectWidth-1))*2*pi);
            float q1=atan((double)abs((Inner.y-Outer.y)/(Inner.x-Outer.x)));
            float r0=sqrt(pow((double)(Inner.x-Outer.x),2)+pow((double)(Inner.y-Outer.y),2));
            float q=(i/(RectWidth-1))*2*pi+q1;
            if(q<0)
                q=-q;
            float q2=asin(r0*sin(q)/Outer.r);
            float Ia=sqrt(pow((double)r0,2)+pow((double)Outer.r,2)-2*r0*Outer.r*cos(pi-q2-q));
            int x2=Inner.x+Ia*cos((i/(RectWidth-1))*2*pi);
            int y2=Inner.y+Ia*sin((i/(RectWidth-1))*2*pi);
            for(j=0.0;j<RectHeight;j++)
            {
                float lamuda=j/(RectHeight-1);
                i0=(1-lamuda)*x1+lamuda*x2;
                j0=(1-lamuda)*y1+lamuda*y2;
                lpDst=lpNewDIBBits+lNewLineBytes*((long)j)+(long)i;
                *lpDst=DLInsAlgorithm(i0,j0);
            }
        }
    }
    if(Inner.x<Outer.x&&Inner.y<=Outer.y)
    {
        for (i=0.0;i<RectWidth;i++)
        {
            int x1=Inner.x+Inner.r*cos((i/(RectWidth-1))*2*pi);
            int y1=Inner.y+Inner.r*sin((i/(RectWidth-1))*2*pi);
            float q1=atan((double)abs((Inner.y-Outer.y)/(Inner.x-Outer.x)));
            float r0=sqrt(pow((double)(Inner.x-Outer.x),2)+pow((double)(Inner.y-Outer.y),2));
            float q=(i/(RectWidth-1))*2*pi-q1;
            if(q<0)
                q=-q;
            if(q>pi)
                q=2*pi-q;
            float q2=asin(r0*sin(q)/Outer.r);
            float Ia=sqrt(pow((double)r0,2)+pow((double)Outer.r,2)-2*r0*Outer.r*cos(pi-q-q2));
            int x2=Inner.x+Ia*cos((i/(RectWidth-1))*2*pi);
            int y2=Inner.y+Ia*sin((i/(RectWidth-1))*2*pi);
            for(j=0.0;j<RectHeight;j++)
            {
                float lamuda=j/(RectHeight-1);
                i0=(1-lamuda)*x1+lamuda*x2;
                j0=(1-lamuda)*y1+lamuda*y2;
                lpDst=lpNewDIBBits+lNewLineBytes*((long)j)+(long)i;
                *lpDst=DLInsAlgorithm(i0,j0);
            }
        }

    }
    if(Inner.x>Outer.x&&Inner.y<=Outer.y)
    {
        for (i=0.0;i<RectWidth;i++)
        {
            int x1=Inner.x+Inner.r*cos((i/(RectWidth-1))*2*pi);
            int y1=Inner.y+Inner.r*sin((i/(RectWidth-1))*2*pi);
            float q1=atan((double)abs((Inner.y-Outer.y)/(Inner.x-Outer.x)));
            float r0=sqrt(pow((double)(Inner.x-Outer.x),2)+pow((double)(Inner.y-Outer.y),2));
            float q=pi-( i/(RectWidth-1))*2*pi-q1;
            if(q<0)
                q=-q;
            float q2=asin(r0*sin(q)/Outer.r);
            float Ia=sqrt(pow((double)r0,2)+pow((double)Outer.r,2)-2*r0*Outer.r*cos(pi-q-q2));
            int x2=Inner.x+Ia*cos((i/(RectWidth-1))*2*pi);
            int y2=Inner.y+Ia*sin((i/(RectWidth-1))*2*pi);
            for(j=0.0;j<RectHeight;j++)
            {
                float lamuda=j/(RectHeight-1);
                i0=(1-lamuda)*x1+lamuda*x2;
                j0=(1-lamuda)*y1+lamuda*y2;
                lpDst=lpNewDIBBits+lNewLineBytes*((long)j)+(long)i;
                *lpDst=DLInsAlgorithm(i0,j0);
            }
        }
    }
    return true;
}

unsigned char BMPFile::DLInsAlgorithm(float x, float y)
{
    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    long lWidth = (long)m_infoHeader.biWidth;
    long lHeight = (long)m_infoHeader.biHeight;
    long lLineBytes = WIDTHBYTES(m_infoHeader.biWidth*8);

//    LPSTR lpDIBBits;
//    long lWidth,lHeight;
    long i1,i2;
    long j1,j2;
    unsigned char f1,f2,f3,f4;
    unsigned char f12,f34;
    double LIMIT=0.0001;
//    long lLineBytes;
//    lpDIBBits=::FindDIBBits(lpDIB);
//    lWidth=::DIBWidth(lpDIB);
//    lHeight=::DIBHeight(lpDIB);
//    lLineBytes=WIDTHBYTES(lWidth*8);
    i1=(long)x;
    i2=i1+1;
    j1=(long)y;
    j2=j1+1;
    if((x<0)||(x>lWidth-1)||(y<0)||(y>lHeight-1))
    {
    return 255;
    }
    else
    {
        if(abs(x-lWidth+1)<=LIMIT)
        {
            if(abs(y-lHeight+1)<=LIMIT)
            {
                f1=*(lpDIBBits+lLineBytes*j1+i1);
                return (unsigned char) f1;
            }
            else
            {
                f1=*(lpDIBBits+lLineBytes*j1+i1);
                f3=*(lpDIBBits+lLineBytes*j1+i2);
                return unsigned char (f1+(y-j1)*(f3-f1));
            }
        }
        else if(abs(y-lHeight+1)<=LIMIT)
        {
            f1=*(lpDIBBits+lLineBytes*j1+i1);
            f2=*(lpDIBBits+lLineBytes*j2+i1);
            return unsigned char (f1+(x-i1)*(f2-f1));
        }
        else
        {
            f1=(unsigned char )*(lpDIBBits+lLineBytes*j1+i1);
            f2=(unsigned char) *(lpDIBBits+lLineBytes*j2+i1);
            f3=(unsigned char) *(lpDIBBits+lLineBytes*j1+i2);
            f4=(unsigned char) *(lpDIBBits+lLineBytes*j2+i2);
            f12=f1+(x-i1)*(f2-f1);
            f34=f3+(x-i1)*(f4-f3);
            return unsigned char (f12+(y-j1)*(f34-f12));
        }
    }
    return 0;
}

//la pu la si bian huan,er zhi hua
void BMPFile::LOGBin(LPSTR pNewPtr)
{
    char* lpDIBBits = pNewPtr + m_fileHeader.bfOffBits;
    const long lWidth=512;
    const long lHeight=128;
    long lLineBytes = WIDTHBYTES(lWidth*8);

//    LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
//    LPSTR lpDIBBits=::FindDIBBits(lpDIB);
//    ::GlobalUnlock((HGLOBAL)hDIB);
//    const long lWidth=512;
//    const long lHeight=128;
//    LONG lLineBytes;
//    lLineBytes=WIDTHBYTES(lWidth*8);
    float(*LoG)[lWidth]=new float[lHeight][lWidth];
    for(long j=0;j<lHeight;j++)
    {
        LoG[j][0]=((unsigned char)*(lpDIBBits+lLineBytes*j))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(+0.0855);
        LoG[j][1]=((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(-0.7420);
        LoG[j][2]=((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+9))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(-0.1771);
           LoG[j][3]=((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+9))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+10))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(0.2913);
        LoG[j][4]=((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+9))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+10))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+11))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(0.4462);
        LoG[j][5]=((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+9))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+10))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+11))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+12))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(0.3573);
        LoG[j][6]=((unsigned char)*(lpDIBBits+lLineBytes*j+6))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+7))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+8))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+9))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+10))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+11))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+12))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+13))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+5))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+4))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+3))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+2))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+1))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j))*(0.2007);
        for(long i=7;i<lWidth-7;i++)
        {
            LoG[j][i]=((unsigned char)*(lpDIBBits+lLineBytes*j+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+1))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+2))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+3))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+4))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+5))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+6))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i+7))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-1))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-2))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-3))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-4))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-5))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-6))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+i-7))*(0.0855);
        }
        LoG[j][lWidth-1]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(+0.0855);
        LoG[j][lWidth-2]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(-0.7420);
        LoG[j][lWidth-3]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-10))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(-0.1771);
        LoG[j][lWidth-4]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-10))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-11))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(0.2913);
        LoG[j][lWidth-5]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-10))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-11))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-12))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(0.4462);
        LoG[j][lWidth-6]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-10))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-11))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-12))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-13))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(0.3573);
        LoG[j][lWidth-7]=((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-7))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-8))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-9))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-10))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-11))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-12))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-13))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-14))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-6))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-5))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-4))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-3))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-2))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*j+lWidth-1))*(0.2007);
    }
    float (*LoGG)[lWidth]=new float[lHeight][lWidth];
//    long i;
    for(long i=0;i<lWidth;i++)
    {
        LoGG[0][i]=LoG[0][i]+0.9113*LoG[1][i]+0.6896*LoG[2][i]+0.4334*LoG[3][i]+0.2262*LoG[4][i]+0.0980*LoG[5][i]+0.0353*LoG[6][i]+0.0105*LoG[7][i];
        LoGG[1][i]=LoG[1][i]+0.9113*LoG[2][i]+0.6896*LoG[3][i]+0.4334*LoG[4][i]+0.2262*LoG[5][i]+0.0980*LoG[6][i]+0.0353*LoG[7][i]+0.0105*LoG[8][i]
                   +0.9113*LoG[0][i];
        LoGG[2][i]=LoG[2][i]+0.9113*LoG[3][i]+0.6896*LoG[4][i]+0.4334*LoG[5][i]+0.2262*LoG[6][i]+0.0980*LoG[7][i]+0.0353*LoG[8][i]+0.0105*LoG[9][i]+
                    0.9113*LoG[1][i]+0.6896*LoG[0][i];
        LoGG[3][i]=LoG[3][i]+0.9113*LoG[4][i]+0.6896*LoG[5][i]+0.4334*LoG[6][i]+0.2262*LoG[7][i]+0.0980*LoG[8][i]+0.0353*LoG[9][i]+0.0105*LoG[10][i]+
                    0.9113*LoG[2][i]+0.6896*LoG[1][i]+0.4334*LoG[0][i];
        LoGG[4][i]=LoG[4][i]+0.9113*LoG[5][i]+0.6896*LoG[6][i]+0.4334*LoG[7][i]+0.2262*LoG[8][i]+0.0980*LoG[9][i]+0.0353*LoG[10][i]+0.0105*LoG[11][i]+
                    0.9113*LoG[3][i]+0.6896*LoG[2][i]+0.4334*LoG[1][i]+0.2262*LoG[0][i];
        LoGG[5][i]=LoG[5][i]+0.9113*LoG[6][i]+0.6896*LoG[7][i]+0.4334*LoG[8][i]+0.2262*LoG[9][i]+0.0980*LoG[10][i]+0.0353*LoG[11][i]+0.0105*LoG[12][i]+
                    0.9113*LoG[4][i]+0.6896*LoG[3][i]+0.4334*LoG[2][i]+0.2262*LoG[1][i]+0.0980*LoG[0][i];
        LoGG[6][i]=LoG[6][i]+0.9113*LoG[7][i]+0.6896*LoG[8][i]+0.4334*LoG[9][i]+0.2262*LoG[10][i]+0.0980*LoG[11][i]+0.0353*LoG[12][i]+0.0105*LoG[13][i]+
                    0.9113*LoG[5][i]+0.6896*LoG[4][i]+0.4334*LoG[3][i]+0.2262*LoG[2][i]+0.0980*LoG[1][i]+0.0353*LoG[0][i];
        for(long j=7;j<lHeight-7;j++)
        {
            LoGG[j][i]=LoG[j][i]+0.9113*LoG[j+1][i]+0.6896*LoG[j+2][i]+0.4334*LoG[j+3][i]+0.2262*LoG[j+4][i]+0.0980*LoG[j+5][i]+0.0353*LoG[j+6][i]+0.0105*LoG[j+7][i]+
                 0.9113*LoG[j-1][i]+0.6896*LoG[j-2][i]+0.4334*LoG[j-3][i]+0.2262*LoG[j-4][i]+0.0980*LoG[j-5][i]+0.0353*LoG[j-6][i]+0.0105*LoG[j-7][i];

        }
        LoGG[lHeight-1][i]=LoG[lHeight-1][i]+0.9113*LoG[lHeight-2][i]+0.6896*LoG[lHeight-3][i]+0.4334*LoG[lHeight-4][i]+0.2262*LoG[lHeight-5][i]+0.0980*LoG[lHeight-6][i]+0.0353*LoG[lHeight-7][i]+0.0105*LoG[lHeight-8][i];
        LoGG[lHeight-2][i]=LoG[lHeight-2][i]+0.9113*LoG[lHeight-3][i]+0.6896*LoG[lHeight-4][i]+0.4334*LoG[lHeight-5][i]+0.2262*LoG[lHeight-6][i]+0.0980*LoG[lHeight-7][i]+0.0353*LoG[lHeight-8][i]+0.0105*LoG[lHeight-9][i]
                            +0.9113*LoG[lHeight-1][i];
        LoGG[lHeight-3][i]=LoG[lHeight-3][i]+0.9113*LoG[lHeight-4][i]+0.6896*LoG[lHeight-5][i]+0.4334*LoG[lHeight-6][i]+0.2262*LoG[lHeight-7][i]+0.0980*LoG[lHeight-8][i]+0.0353*LoG[lHeight-9][i]+0.0105*LoG[lHeight-10][i]+
                            0.9113*LoG[lHeight-2][i]+0.6896*LoG[lHeight-1][i];
        LoGG[lHeight-4][i]=LoG[lHeight-4][i]+0.9113*LoG[lHeight-5][i]+0.6896*LoG[lHeight-6][i]+0.4334*LoG[lHeight-7][i]+0.2262*LoG[lHeight-8][i]+0.0980*LoG[lHeight-9][i]+0.0353*LoG[lHeight-10][i]+0.0105*LoG[lHeight-11][i]+
                            0.9113*LoG[lHeight-3][i]+0.6896*LoG[lHeight-2][i]+0.4334*LoG[lHeight-1][i];
        LoGG[lHeight-5][i]=LoG[lHeight-5][i]+0.9113*LoG[lHeight-6][i]+0.6896*LoG[lHeight-7][i]+0.4334*LoG[lHeight-8][i]+0.2262*LoG[lHeight-9][i]+0.0980*LoG[lHeight-10][i]+0.0353*LoG[lHeight-11][i]+0.0105*LoG[lHeight-12][i]+
                            0.9113*LoG[lHeight-4][i]+0.6896*LoG[lHeight-3][i]+0.4334*LoG[lHeight-2][i]+0.2262*LoG[lHeight-1][i];
        LoGG[lHeight-6][i]=LoG[lHeight-6][i]+0.9113*LoG[lHeight-7][i]+0.6896*LoG[lHeight-8][i]+0.4334*LoG[lHeight-9][i]+0.2262*LoG[lHeight-10][i]+0.0980*LoG[lHeight-11][i]+0.0353*LoG[lHeight-12][i]+0.0105*LoG[lHeight-13][i]+
                            0.9113*LoG[lHeight-5][i]+0.6896*LoG[lHeight-4][i]+0.4334*LoG[lHeight-3][i]+0.2262*LoG[lHeight-2][i]+0.0980*LoG[lHeight-1][i];
        LoGG[lHeight-7][i]=LoG[lHeight-7][i]+0.9113*LoG[lHeight-8][i]+0.6896*LoG[lHeight-9][i]+0.4334*LoG[lHeight-10][i]+0.2262*LoG[lHeight-11][i]+0.0980*LoG[lHeight-12][i]+0.0353*LoG[lHeight-13][i]+0.0105*LoG[lHeight-14][i]+
                            0.9113*LoG[lHeight-6][i]+0.6896*LoG[lHeight-5][i]+0.4334*LoG[lHeight-4][i]+0.2262*LoG[lHeight-3][i]+0.0980*LoG[lHeight-2][i]+0.0353*LoG[lHeight-1][i];
    }
    float LoGy[lHeight][lWidth];
    for(long i=0;i<lWidth;i++)
    {
        LoGy[0][i]=((unsigned char)*(lpDIBBits+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(+0.0855);
        LoGy[1][i]=((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+i))*(-0.7420);
        LoGy[2][i]=((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*9+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-0.1771);
        LoGy[3][i]=((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*9+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*10+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(0.2913);
        LoGy[4][i]=((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*9+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*10+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*11+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(0.4462);
        LoGy[5][i]=((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*9+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*10+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*11+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*12+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*1+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(0.3573);
        LoGy[6][i]=((unsigned char)*(lpDIBBits+lLineBytes*6+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*7+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*8+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*9+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*10+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*11+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*12+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*13+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*14+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*5+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*4+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*3+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*2+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes+i))*(0.2007);
        for(long j=7;j<lHeight-7;j++)
        {
           LoGy[j][i]=((unsigned char)*(lpDIBBits+lLineBytes*j+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+1)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+2)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+3)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+4)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+5)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+6)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j+7)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-1)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-2)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-3)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-4)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-5)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-6)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(j-7)+i))*(0.0855);
        }
        LoGy[lHeight-1][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(+0.0855);
        LoGy[lHeight-2][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(-0.7420);
        LoGy[lHeight-3][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-10)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(-0.1771);
        LoGy[lHeight-4][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-10)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-11)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(0.2913);
        LoGy[lHeight-5][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-10)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-11)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-12)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(0.4462);
        LoGy[lHeight-6][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-10)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-11)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-12)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-13)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(0.3573);
        LoGy[lHeight-7][i]=((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-7)+i))*(-1)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-8)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-9)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-10)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-11)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-12)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-13)+i))*(0.2007)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-14)+i))*(+0.0855)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-6)+i))*(-0.7420)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-5)+i))*(-0.1771)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-4)+i))*(0.2913)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-3)+i))*(0.4462)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-2)+i))*(0.3573)+
          ((unsigned char)*(lpDIBBits+lLineBytes*(lHeight-1)+i))*(0.2007);

    }
    float LoGGy[lHeight][lWidth];
    for(long j=0;j<lHeight;j++)
    {
        LoGGy[j][0]=LoGy[j][0]+0.9113*LoGy[j][1]+0.6896*LoGy[j][2]+0.4334*LoGy[j][3]+0.2262*LoGy[j][4]+0.0980*LoGy[j][5]+0.0353*LoGy[j][6]+0.0105*LoGy[j][7];
        LoGGy[j][1]=LoGy[j][1]+0.9113*LoGy[j][2]+0.6896*LoGy[j][3]+0.4334*LoGy[j][4]+0.2262*LoGy[j][5]+0.0980*LoGy[j][6]+0.0353*LoGy[j][7]+0.0105*LoGy[j][8]
                    +0.9113*LoGy[j][0];
        LoGGy[j][2]=LoGy[j][2]+0.9113*LoGy[j][3]+0.6896*LoGy[j][4]+0.4334*LoGy[j][5]+0.2262*LoGy[j][6]+0.0980*LoGy[j][7]+0.0353*LoGy[j][8]+0.0105*LoGy[j][9]+
                    0.9113*LoGy[j][1]+0.6896*LoGy[j][0];
        LoGGy[j][3]=LoGy[j][3]+0.9113*LoGy[j][4]+0.6896*LoGy[j][5]+0.4334*LoGy[j][6]+0.2262*LoGy[j][7]+0.0980*LoGy[j][8]+0.0353*LoGy[j][9]+0.0105*LoGy[j][10]+
                    0.9113*LoGy[j][2]+0.6896*LoGy[j][1]+0.4334*LoGy[j][0];
        LoGGy[j][4]=LoGy[j][4]+0.9113*LoGy[j][5]+0.6896*LoGy[j][6]+0.4334*LoGy[j][7]+0.2262*LoGy[j][8]+0.0980*LoGy[j][9]+0.0353*LoGy[j][10]+0.0105*LoGy[j][11]+
                    0.9113*LoGy[j][3]+0.6896*LoGy[j][2]+0.4334*LoGy[j][1]+0.2262*LoGy[j][0];
        LoGGy[j][5]=LoGy[j][5]+0.9113*LoGy[j][6]+0.6896*LoGy[j][7]+0.4334*LoGy[j][8]+0.2262*LoGy[j][9]+0.0980*LoGy[j][10]+0.0353*LoGy[j][11]+0.0105*LoGy[j][12]+
                    0.9113*LoGy[j][4]+0.6896*LoGy[j][3]+0.4334*LoGy[j][2]+0.2262*LoGy[j][1]+0.0980*LoGy[j][0];
        LoGGy[j][6]=LoGy[j][6]+0.9113*LoGy[j][7]+0.6896*LoGy[j][8]+0.4334*LoGy[j][9]+0.2262*LoGy[j][10]+0.0980*LoGy[j][11]+0.0353*LoGy[j][12]+0.0105*LoGy[j][13]+
                    0.9113*LoGy[j][5]+0.6896*LoGy[j][4]+0.4334*LoGy[j][3]+0.2262*LoGy[j][2]+0.0980*LoGy[j][1]+0.0353*LoGy[j][0];
        for(long i=7;i<lWidth-7;i++)
        {
            LoGGy[j][i]=LoGy[j][i]+0.9113*LoGy[j][i+1]+0.6896*LoGy[j][i+2]+0.4334*LoGy[j][i+3]+0.2262*LoGy[j][i+4]+0.0980*LoGy[j][i+5]+0.0353*LoGy[j][i+6]+0.0105*LoGy[j][i+7]+
                 0.9113*LoGy[j][i-1]+0.6896*LoGy[j][i-2]+0.4334*LoGy[j][i-3]+0.2262*LoGy[j][i-4]+0.0980*LoGy[j][i-5]+0.0353*LoGy[j][i-6]+0.0105*LoGy[j][i-7];
        }
        LoGGy[j][lWidth-1]=LoGy[j][lWidth-1]+0.9113*LoGy[j][lWidth-2]+0.6896*LoGy[j][lWidth-3]+0.4334*LoGy[j][lWidth-4]+0.2262*LoGy[j][lWidth-5]+0.0980*LoGy[j][lWidth-6]+0.0353*LoGy[j][lWidth-7]+0.0105*LoGy[j][lWidth-8];
        LoGGy[j][lWidth-2]=LoGy[j][lWidth-2]+0.9113*LoGy[j][lWidth-3]+0.6896*LoGy[j][lWidth-4]+0.4334*LoGy[j][lWidth-5]+0.2262*LoGy[j][lWidth-6]+0.0980*LoGy[j][lWidth-7]+0.0353*LoGy[j][lWidth-8]+0.0105*LoGy[j][lWidth-9]
                            +0.9113*LoGy[j][lWidth-1];
        LoGGy[j][lWidth-3]=LoGy[j][lWidth-3]+0.9113*LoGy[j][lWidth-4]+0.6896*LoGy[j][lWidth-5]+0.4334*LoGy[j][lWidth-6]+0.2262*LoGy[j][lWidth-7]+0.0980*LoGy[j][lWidth-8]+0.0353*LoGy[j][lWidth-9]+0.0105*LoGy[j][lWidth-10]+
                            0.9113*LoGy[j][lWidth-2]+0.6896*LoGy[j][lWidth-1];
        LoGGy[j][lWidth-4]=LoGy[j][lWidth-4]+0.9113*LoGy[j][lWidth-5]+0.6896*LoGy[j][lWidth-6]+0.4334*LoGy[j][lWidth-7]+0.2262*LoGy[j][lWidth-8]+0.0980*LoGy[j][lWidth-9]+0.0353*LoGy[j][lWidth-10]+0.0105*LoGy[j][lWidth-11]+
                            0.9113*LoGy[j][lWidth-3]+0.6896*LoGy[j][lWidth-2]+0.4334*LoGy[j][lWidth-1];
        LoGGy[j][lWidth-5]=LoGy[j][lWidth-5]+0.9113*LoGy[j][lWidth-6]+0.6896*LoGy[j][lWidth-7]+0.4334*LoGy[j][lWidth-8]+0.2262*LoGy[j][lWidth-9]+0.0980*LoGy[j][lWidth-10]+0.0353*LoGy[j][lWidth-11]+0.0105*LoGy[j][lWidth-12]+
                            0.9113*LoGy[j][lWidth-4]+0.6896*LoGy[j][lWidth-3]+0.4334*LoGy[j][lWidth-2]+0.2262*LoGy[j][lWidth-1];
        LoGGy[j][lWidth-6]=LoGy[j][lWidth-6]+0.9113*LoGy[j][lWidth-7]+0.6896*LoGy[j][lWidth-8]+0.4334*LoGy[j][lWidth-9]+0.2262*LoGy[j][lWidth-10]+0.0980*LoGy[j][lWidth-11]+0.0353*LoGy[j][lWidth-12]+0.0105*LoGy[j][lWidth-13]+
                            0.9113*LoGy[j][lWidth-5]+0.6896*LoGy[j][lWidth-4]+0.4334*LoGy[j][lWidth-3]+0.2262*LoGy[j][lWidth-2]+0.0980*LoGy[j][lWidth-1];
        LoGGy[j][lWidth-7]=LoGy[j][lWidth-7]+0.9113*LoGy[j][lWidth-8]+0.6896*LoGy[j][lWidth-9]+0.4334*LoGy[j][lWidth-10]+0.2262*LoGy[j][lWidth-11]+0.0980*LoGy[j][lWidth-12]+0.0353*LoGy[j][lWidth-13]+0.0105*LoGy[j][lWidth-14]+
                            0.9113*LoGy[j][lWidth-6]+0.6896*LoGy[j][lWidth-5]+0.4334*LoGy[j][lWidth-4]+0.2262*LoGy[j][lWidth-3]+0.0980*LoGy[j][lWidth-2]+0.0353*LoGy[j][lWidth-1];
    }
    for(long j=0;j<lHeight;j++)
    {
        for(long i=0;i<lWidth;i++)
        {
            LoGG[j][i]=LoGG[j][i]+LoGGy[j][i];
        }
    }
    for(long j=0;j<lHeight;j++)
    {
        int marker=0;
        for (long i=0;i<lWidth;i++)
        {
            if(LoGG[j][i]>0)
            {
                marker=1;
                *(lpDIBBits+lLineBytes*j+i)=(unsigned char)255;
            }
            if(LoGG[j][i]<0)
            {
                marker=0;
                *(lpDIBBits+lLineBytes*j+i)=(unsigned char)0;
            }
            if(LoGG[j][i]==0)
            {
                if(marker==1)
                    *(lpDIBBits+lLineBytes*j+i)=(unsigned char)255;
                else *(lpDIBBits+lLineBytes*j+i)=(unsigned char)0;
            }
        }
    }
    delete[] LoG;
    delete[] LoGG;

    return;
}

//xing tai xue chu li
void BMPFile::Morphological(LPSTR pNewPtr)
{
    char* lpDIBBits = pNewPtr + m_fileHeader.bfOffBits;
    const long lWidth=512;
    const long lHeight=128;
//    uint32 lLineBytes = WIDTHBYTES(lWidth*8);

    char* lpNewDIBBits = new char[lWidth * lHeight];
    if( nullptr == lpNewDIBBits)
    {
        qWarning() << "New error";
        return;
    }
    memset((void*)lpNewDIBBits,0,lWidth*lHeight);

    int m=3;
    int n=3;
    int structure[3][3]={0,0,0,0,0,0,0,0,0};
    long i;
    long j;
    LPSTR	lpSrc;
    LPSTR	lpDst;
    unsigned char pixel;

    for(j=1;j<lHeight-1;j++)
    {
        for(i=1;i<lWidth-1;i++)
        {
            lpSrc=(char *)lpDIBBits+lWidth*j+i;
            lpDst=(char *)lpNewDIBBits+lWidth*j + i;
            pixel=(unsigned char)*lpSrc;
            if(pixel!=255&&*lpSrc!=0)
            {
                qWarning() << "Not Binarize picture";
                return ;
            }
            *lpDst=(unsigned char)255;
            for(m=0;m<3;m++ )
            {
                for(n=0;n<3;n++)
                {
                    if(structure[m][n]==-1)
                        continue;
                    pixel=*(lpSrc+((2-m)-1)*lWidth+(n-1));
                    if(pixel==0)
                    {
                        *lpDst=(unsigned char)0;
                        break;
                    }
                }
            }
        }
    }
    memcpy(lpDIBBits,lpNewDIBBits,lWidth*lHeight);
    lpDst=(char *)lpNewDIBBits;
    memset((void*)lpDst,0,lWidth*lHeight);
    for(j=1;j<lHeight-1;j++)
    {
        for(i=1;i<lWidth-1;i++)
        {
            lpSrc=(char *)lpDIBBits+lWidth*j+i;
            lpDst=(char *)lpNewDIBBits+lWidth*j+i;
            pixel=(unsigned char)*lpSrc;
            if(pixel!=255&&*lpSrc!=0)
            {
                qWarning() << "Not Binarize picture";
                return ;
            }
            *lpDst=(unsigned char)0;
            for(m=0;m<3;m++ )
            {
                for(n=0;n<3;n++)
                {
                    if(structure[m][n]==-1)
                        continue;
                    pixel=*(lpSrc+((2-m)-1)*lWidth+(n-1));
                    if(pixel==255)
                    {
                        *lpDst=(unsigned char)255;
                        break;
                    }
                }
            }
        }
    }
    memcpy(lpDIBBits,lpNewDIBBits,lWidth*lHeight);

    delete[] lpNewDIBBits;
    return;
}

void BMPFile::MarkthePoint(LPSTR pNewPtr,PointInformation *PointInfor, int &tab)
{
    char* lpDIBBits = pNewPtr + m_fileHeader.bfOffBits;
    const long lWidth=512;
    const long lHeight=128;
    long lLineBytes = WIDTHBYTES(lWidth*8);

//    LPSTR lpDIB=(LPSTR)::GlobalLock((HGLOBAL)hDIB);
//    LPSTR lpDIBBits=::FindDIBBits(lpDIB);
//    ::GlobalUnlock((HGLOBAL)hDIB);
    int taber=0;
    LPSTR src=lpDIBBits;
    unsigned char pre=*src;
    for(int i=0;i<255;i++)
    {
        PointInfor[i].useful=false;
    }
    if(pre==255)
    {
        PointInfor[1].left=0;
        PointInfor[1].right=0;
        PointInfor[1].bottom=0;
        PointInfor[1].top=0;
        PointInfor[1].useful=true;
        PointInfor[1].xsum=0;
        PointInfor[1].ysum=0;
        PointInfor[1].size=1;
        *src=1;
        taber=taber+1;
    }
//    CList<long,long> unusedtab;
    QList<long> unusedtab;
    long i;

    for(i=1;i<lWidth;i++)
    {
        src=lpDIBBits+i;
        if((unsigned char)*src==255)
        {
            if(pre!=0)
            {
                *src=(unsigned char)pre;
                PointInfor[(unsigned long)*src].right=i;
                PointInfor[(unsigned long)*src].size+=1;
                PointInfor[(unsigned long)*src].xsum+=i;
             }
            else
            {
                tab=tab+1;
                if(tab>=255)
                {
                    tab=255;
                    *src=0;
                }
                else
                {
                *src=(unsigned char)taber+1;
                PointInfor[taber].useful=true;
                PointInfor[taber].top=0;
                PointInfor[taber].bottom=0;
                PointInfor[taber].left=i;
                PointInfor[taber].right=i;
                PointInfor[taber].size=1;
                PointInfor[taber].xsum=i;
                PointInfor[taber].ysum=0;
                }
             }
         }
         pre=*src;
    }

    for(long j=1;j<lHeight;j++)
    {
        LPSTR src_a=lpDIBBits+(j-1)*lLineBytes;
        LPSTR src=lpDIBBits+j*lLineBytes;
//        *src = 255;
        if(1)
//        if( *src = 255 )
        {
            if(*src_a!=0)
            {
                *src=*src_a;
                PointInfor[(unsigned long)*src_a].bottom=j;
                PointInfor[(unsigned long)*src_a].size+=1;
                PointInfor[(unsigned long)*src_a].ysum+=j;
            }
            else
            {
                if(unusedtab.isEmpty()!=true)
                {
                    long t=(unsigned char)unusedtab.front();
                    *src=t;
                    unusedtab.pop_front();
                    PointInfor[t].useful=true;
                    PointInfor[t].left=i;
                    PointInfor[t].right=i;
                    PointInfor[t].top=j;
                    PointInfor[t].bottom=j;
                    PointInfor[t].size=1;
                    PointInfor[t].xsum=0;
                    PointInfor[t].ysum=j;
                }
                else
                {
                    taber=taber+1;
                    if(taber>=255)
                    {
                        taber=255;
                        *src=0;
                    }
                    else
                    {
                        *src=(unsigned char)taber;
                        PointInfor[taber].useful=true;
                        PointInfor[taber].left=i;
                        PointInfor[taber].right=i;
                        PointInfor[taber].top=j;
                        PointInfor[taber].bottom=j;
                        PointInfor[taber].size=1;
                        PointInfor[taber].xsum=i;
                        PointInfor[taber].ysum=j;
                    }
                }

            }
            for(long i=1;i<lWidth;i++)
            {
                LPSTR  src_a=lpDIBBits+lLineBytes*(j-1)+i-1;
                LPSTR  src_b=lpDIBBits+lLineBytes*(j-1)+i;
                LPSTR  src_c=lpDIBBits+lLineBytes*j+i-1;
                LPSTR  src=lpDIBBits+lLineBytes*j+i;
                if(*src==0)
                    continue;
                if(*src!=0)
                {
                    //a is not marked
                    if(*src_a!=0)
                    {
                        *src=*src_a;
                        long point=(unsigned char)*src;
                        if(PointInfor[point].right<i)
                            PointInfor[point].right=i;
                        PointInfor[point].size+=1;
                        if(PointInfor[point].bottom<j)
                            PointInfor[point].bottom=j;
                        PointInfor[point].xsum+=i;
                        PointInfor[point].ysum+=j;
                            continue;
                    }
                    //b or c is marked
                    if(*src_b!=0&&*src_c==0)
                    {
                        *src=*src_b;
                        long point=(unsigned char)*src;
                        if(PointInfor[point].right<i)
                            PointInfor[point].right=i;
                        PointInfor[point].size+=1;
                        if(PointInfor[point].bottom<j)
                            PointInfor[point].bottom=j;
                        PointInfor[point].xsum+=i;
                        PointInfor[point].ysum+=j;
                        continue;
                    }
                    if(*src_b==0&&*src_c!=0)
                    {
                        *src=*src_c;
                        long point=(unsigned char)*src;
                        if(PointInfor[point].right<i)
                            PointInfor[point].right=i;
                        PointInfor[point].size+=1;
                        if(PointInfor[point].bottom<j)
                            PointInfor[point].bottom=j;
                        PointInfor[point].xsum+=i;
                        PointInfor[point].ysum+=j;
                        continue;
                    }
                    //b and c all are marked at the same
                    if(*src_b!=0&&*src_c!=0&&*src_b==*src_c)
                    {
                        *src=*src_c;
                        long point=(unsigned char)*src;
                        if(PointInfor[point].right<i)
                            PointInfor[point].right=i;
                        PointInfor[point].size+=1;
                        if(PointInfor[point].bottom<j)
                            PointInfor[point].bottom=j;
                        PointInfor[point].xsum+=i;
                        PointInfor[point].ysum+=j;
                        continue;
                    }
                    //b and c all are marked,but not the same
                    if(*src_b!=0&&*src_c!=0&&*src_b!=*src_c)
                    {
                    *src=((unsigned char)*src_b<(unsigned char)*src_c)?(unsigned char)*src_b:(unsigned char) *src_c;
                    long tmp=((unsigned char)*src_b<(unsigned char)*src_c)? (unsigned char)*src_c:(unsigned char)*src_b;
                    if(PointInfor[(unsigned char)*src_c].left<PointInfor[(unsigned char)*src_b].left)
                        PointInfor[(unsigned char)*src].left=PointInfor[(unsigned char)*src_c].left;
                    else
                        PointInfor[(unsigned char)*src].left=PointInfor[(unsigned char)*src_b].left;
                    if(PointInfor[(unsigned char)*src_c].top<PointInfor[(unsigned char)*src_b].top)
                        PointInfor[(unsigned char)*src].top=PointInfor[(unsigned char)*src_c].top;
                    else
                        PointInfor[(unsigned char)*src].top=PointInfor[(unsigned char)*src_b].top;
                    if(PointInfor[(unsigned char)*src_c].right>PointInfor[(unsigned char)*src_b].right)
                        PointInfor[(unsigned char)*src].right=PointInfor[(unsigned char)*src_c].right;
                    else
                        PointInfor[(unsigned char)*src].right=PointInfor[(unsigned char)*src_b].right;
                    if(PointInfor[(unsigned char)*src].right<i)
                        PointInfor[(unsigned char)*src].right=i;
                    PointInfor[(unsigned char)*src].bottom=j;
                    PointInfor[(unsigned char)*src].size=PointInfor[(unsigned char)*src_b].size+PointInfor[(unsigned char)*src_c].size+1;
                    PointInfor[(unsigned char)*src].xsum=PointInfor[(unsigned char)*src_b].xsum+PointInfor[(unsigned char)*src_c].xsum+i;
                    PointInfor[(unsigned char)*src].ysum=PointInfor[(unsigned char)*src_b].ysum+PointInfor[(unsigned char)*src_c].ysum+j;
                    for(long k=PointInfor[tmp].top;k<=PointInfor[tmp].bottom;k++)
                    {
                        for(long l=PointInfor[tmp].left;l<=PointInfor[tmp].right;l++)
                        {
                            LPSTR src1=lpDIBBits+lLineBytes*k+l;
                            if((unsigned char)*src1==(unsigned char)tmp)
                            *src1=*src;
                        }
                    }
                    PointInfor[tmp].useful=false;
                    PointInfor[tmp].left=0;
                    PointInfor[tmp].bottom=0;
                    PointInfor[tmp].right=0;
                    PointInfor[tmp].top=0;
                    PointInfor[tmp].size=0;
                    PointInfor[tmp].xsum=0;
                    PointInfor[tmp].ysum=0;
                    unusedtab.push_back(tmp);
                    continue;
                    }
                    //b and c all are not marked
                    if(*src_b==0&&*src_c==0)
                    {
                        if(unusedtab.isEmpty()!=true)
                        {
                            *src=(unsigned char)unusedtab.front();
                            unusedtab.pop_front();
                            PointInfor[(unsigned char )*src].useful=true;
                            PointInfor[(unsigned char )*src].top=j;
                            PointInfor[(unsigned char )*src].bottom=j;
                            PointInfor[(unsigned char )*src].left=i;
                            PointInfor[(unsigned char )*src].right=i;
                            PointInfor[(unsigned char )*src].size=1;
                            PointInfor[(unsigned char )*src].xsum=i;
                            PointInfor[(unsigned char )*src].ysum=j;
                            continue;
                        }
                        else
                        {
                            taber=taber+1;
                            if(taber>=255)
                            {
                                taber=255;
                                *src=0;
                            }else
                            {
                                *src=(unsigned char)taber;
                                PointInfor[(unsigned char )*src].useful=true;
                                PointInfor[(unsigned char )*src].top=j;
                                PointInfor[(unsigned char )*src].bottom=j;
                                PointInfor[(unsigned char )*src].left=i;
                                PointInfor[(unsigned char )*src].right=i;
                                PointInfor[(unsigned char )*src].size=1;
                                PointInfor[(unsigned char )*src].xsum=i;
                                PointInfor[(unsigned char )*src].ysum=j;
                                continue;
                            }
                        }

                    }
                }
            }
        }
    }
    tab=taber;
}

//PCA

SourceData PCA::getdata(double a[128][7])
{
    SourceData dat;
    int i,j;
    dat.m=128;
    dat.n=7;

    dat.data=new double*[dat.m];
    for(i=0;i<dat.m;i++)
        dat.data[i]=new double[dat.n];
    for(i=0;i<dat.m;i++)
       for(j=0;j<dat.n;j++)
          dat.data[i][j]=a[i][j];
    return dat;
}

PCA::PCA(int m,int n)   //构造函数
{
    columns=n;
    rows=m;
}
void PCA::standarddata(double **a) //数据标准化
{
    double s,ss;
    int i,j;
    for(i=0;i<columns;i++)
    {
        s=0;
        for(j=0;j<rows;j++)
            s+=a[j][i];
        s=s/rows;
        ss=0;
        for(j=0;j<rows;j++)
            ss+=(a[j][i]-s)*(a[j][i]-s);
        ss=ss/(rows-1);
        for(j=0;j<rows;j++)
            a[j][i]=(a[j][i]-s)/sqrt(ss);
    }
}
double  PCA::product(double *a,double *b) //向量乘积
{
    double sum=0;
    for(int i=0;i<columns;i++)
        sum+=a[i]*b[i];
    return sum;
}
double **PCA::matrixproduct(double **a) //求解协方差矩阵
{
    int i,j,k;
    double **c;
    c=new double*[columns];
    for(i=0;i<columns;i++)
       c[i]=new double[columns];
    for(i=0;i<columns;i++)
        for(j=0;j<columns;j++)
        {
            c[i][j]=0;
            for(k=0;k<rows;k++)
                c[i][j]+=a[k][i]*a[k][j];
            c[i][j]/=(rows-1);
        }
   return c;
   for(i=0;i<columns;i++)
      delete[columns]c[i];
   delete [columns]c;
}
void  PCA::zhengjiao(double **v) //向量正交化
{
    double **b;
    double *xx,*yy;
    int i,j;
    xx=new double[columns];
    yy=new double[columns];
    b=new double*[columns];
    for(i=0;i<columns;i++)
       b[i]=new double[columns];
    for(i=0;i<columns;i++)
        b[i][0]=v[i][0];
    for(j=1;j<columns;j++)
        for(i=0;i<columns;i++)
        {
            for(int k=0;k<j;k++)
            {
                for(int t=0;t<columns;t++)
                {
                    xx[t]=b[t][k];
                    yy[t]=v[t][j];
                }
                b[i][j]=v[i][j]-(product(xx,yy)/product(xx,xx))*b[i][k];
            }
        }
    for(i=0;i<columns;i++)
    {
        for(int j=0;j<columns;j++)
            xx[j]=b[j][i];
        yy[i]=sqrt(product(xx,xx));
    }
    for(i=0;i<columns;i++)
        for(j=0;j<columns;j++)
            v[i][j]=b[i][j]/yy[j];
   delete []xx;
   delete []yy;
   for(i=0;i<columns;i++)
      delete[columns]b[i];
   delete [rows]b;
}
void  PCA::swap(double &x,double &y) //数据交换
{
    double d;
    d=x;
    x=y;
    y=d;
}
void  PCA::selectionsort(double *A,double **v)  //特征值和对应的特征向量进行选择排序
{
    int maxindex;
    int i,j;
    for(i=0;i<columns-1;i++)
    {
        maxindex=i; //最大元素的下标设为i
        for(j=i+1;j<columns;j++)
            if(A[j]>A[maxindex])
                maxindex=j;
        swap(A[i],A[maxindex]);
        for(int k=0;k<columns;k++)
            swap(v[k][i],v[k][maxindex]); //对应的特征向量进行交换
    }
}
int PCA::jcb(double **a,double **v,double eps,int jt)
//jacobi求实对称矩阵的特征值和特征向量
{
    int i,j,p,q,l;
    double fm,cn,sn,omega,x,y,d;
    l=1;
    for(i=0;i<=columns-1;i++)    //赋值v=I
    {
        v[i][i]=1.0;
        for(j=0;j<=columns-1;j++)
            if(i!=j) v[i][j]=0;
    }
    while(true)
    {
        fm=0.0;
        for(i=0;i<=columns-1;i++)
            for(j=0;j<=i-1;j++)
            {
                d=fabs(a[i][j]);
                if((i!=j)&&(d>fm))   //取最大的a[p][q]
                {
                    fm=d;p=i;q=j;}
            }
        if(fm<eps) //如果达到给定的精度跳出循环
        {
            return(1);
            break;
        }
        if(l>jt) //如果不能求解
        {
            return(-1);
            break;
        }
        l=l+1;	 //记录迭代次数
        x=-a[p][q];
        y=(a[q][q]-a[p][p])/2.0;
        omega=x/sqrt(x*x+y*y);
        if(y<0.0) omega=-omega;
        sn=1.0+sqrt(1.0-omega*omega);
        sn=omega/sqrt(2.0*sn);  //正弦
        cn=sqrt(1.0-sn*sn);  //余弦
        fm=a[p][p];
        a[p][p]=fm*cn*cn+a[q][q]*sn*sn+a[p][q]*omega;
        a[q][q]=fm*sn*sn+a[q][q]*cn*cn-a[p][q]*omega;
        a[p][q]=y*omega+a[p][q]*(2*cn*cn-1);
        a[q][p]=a[p][q];
        for(j=0;j<=columns-1;j++)
            if((j!=p)&&(j!=q))
            {
                fm=a[p][j];
                a[p][j]=fm*cn+a[q][j]*sn;
                a[q][j]=-fm*sn+a[q][j]*cn;
            }
        for(i=0;i<=columns-1;i++)
            if((i!=p)&&(i!=q))
            {
                fm=a[i][p];
                a[i][p]=fm*cn+a[i][q]*sn;
                a[i][q]=-fm*sn+a[i][q]*cn;
            }
        for(i=0;i<=columns-1;i++)
        {
            fm=v[i][p];
            v[i][p]=fm*cn+v[i][q]*sn;
            v[i][q]=-fm*sn+v[i][q]*cn;
        }
    }
}

int PCA::selectcharactor(double *A,double getratio,double *B) //特征值的提取率
{
    double s=0;
    int i;
    for(int i=0;i<columns;i++)
        s=s+A[i];
    B[0]=A[0]/s;
    for(i=1;i<columns;i++)
        B[i]=B[i-1]+A[i]/s; //特征值的累计贡献率
    if(getratio>1||getratio<0)
        return -1;
    for(i=0;i<columns;i++)
    {
        if(B[i]>=getratio)
        {
           return i+1;
           break;
        }
    }
    if(B[columns-1]<getratio)
        return -1;
}
double **PCA::getProject(int t,double **x,double **v) //获取数据投影
{
    double **C;
    int i;
    C=new double*[rows];
    for(int i=0;i<rows;i++)
       C[i]=new double[t];
    for(i=0;i<rows;i++)
        for(int j=0;j<t;j++)
            C[i][j]=0;
    for(i=0;i<rows;i++)
    {
        for(int j=0;j<t;j++)
            for(int k=0;k<columns;k++)
               C[i][j]+=x[i][k]*v[k][j];
    }
    return  C;
    for(i=0;i<rows;i++)
      delete[t]C[i];
   delete [rows]C;
}
void   PCA::saveProject(const char *projectfile,double **project,int t)
{
    FILE *Ptr;
    Ptr=fopen(projectfile,"w");
    if(Ptr==NULL)
        //cout<<"error"<<endl;
        qWarning() << "Ensure source is selected right";
        return;
    if(Ptr!=NULL)
    {
        for(int i=0;i<rows;i++)
        {
            for(int j=0;j<t;j++)
                fprintf(Ptr,"%12.8f%s",project[i][j],"  ");
            fprintf(Ptr,"\n");
        }
    }
    fclose(Ptr);
}

//PCA结束

void BMPFile::GetCharacterVector(PointInformation *PointInfor,
    int tab, CharacterVector *Character, int length)
{
//    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    const long lWidth=512;
    const long lHeight=128;
    long lLineBytes = WIDTHBYTES(lWidth*8);

    //malloc
    char* lpRecorder = new char[
            lWidth *
            lHeight];
    if( nullptr == lpRecorder)
    {
        qWarning() << "New error";
        delete lpRecorder;
        lpRecorder = nullptr;
        return;
    }
    memset(lpRecorder,0,lHeight*lWidth);
    for(int i=1;i<=tab;i++)
    {
        if(PointInfor[i].useful)
        {
            if(PointInfor[i].top<5&&((PointInfor[i].right-PointInfor[i].left)>80))
            {
                PointInfor[i].useful=false;
                PointInfor[i].top=0;
                PointInfor[i].bottom=0;
                PointInfor[i].right=0;
                PointInfor[i].bottom=0;
                PointInfor[i].size=0;
                PointInfor[i].xsum=0;
                PointInfor[i].ysum=0;
                 continue;
            }
            if(PointInfor[i].bottom>98&&((PointInfor[i].bottom-PointInfor[i].top)>45||
                    (PointInfor[i].right-PointInfor[i].left)>80))
            {
                PointInfor[i].useful=false;
                PointInfor[i].top=0;
                PointInfor[i].bottom=0;
                PointInfor[i].right=0;
                PointInfor[i].bottom=0;
                PointInfor[i].size=0;
                PointInfor[i].xsum=0;
                PointInfor[i].ysum=0;
                continue;
            }
            PointInfor[i].xsum=(float)PointInfor[i].xsum/(float)PointInfor[i].size+0.5;
            PointInfor[i].ysum=(float)PointInfor[i].ysum/(float)PointInfor[i].size+0.5;
            LPSTR src2= lpRecorder+lLineBytes*PointInfor[i].ysum+PointInfor[i].xsum;
            *src2=i;
        }
    }
    for(int i=0;i<length;i++)
    {
        Character[i].type=0;
    }
    int counter=0;
    for(long j=0;j<lHeight;j++)
    {
        for(long i=0;i<lWidth;i++)
        {
            LPSTR src3;
            src3=lpRecorder+lLineBytes*j+i;
            int src_val=(unsigned char)*src3;
            if(src_val!=0)
            {
                Character[counter].left=PointInfor[src_val].left;
                Character[counter].bottom=PointInfor[src_val].bottom;
                Character[counter].top=PointInfor[src_val].top;
                Character[counter].right=PointInfor[src_val].right;
                Character[counter].x=PointInfor[src_val].xsum;
                Character[counter].y=PointInfor[src_val].ysum;
                int dy=PointInfor[src_val].bottom-PointInfor[src_val].top;
                int dx=PointInfor[src_val].right-PointInfor[src_val].left;
                float dydx=(float)dy/(float)dx+0.5;
                float area_ratio=(float) PointInfor[src_val].size/(float)(dx*dy);
                if(area_ratio<=0.5)
                {
                    if(PointInfor[src_val].size<100)
                        Character[counter].type=9;
                    else
                        Character[counter].type=8;

                }
                else
                {
                    if(dydx<2&&dydx>0.5)
                    {
                        if(PointInfor[src_val].size<40)
                            Character[counter].type=1;
                        if(PointInfor[src_val].size<160&&PointInfor[src_val].size>=40)
                            Character[counter].type=2;
                        if(PointInfor[src_val].size>=160)
                            Character[counter].type=3;
                    }
                    if(dydx>=2)
                    {
                        if(PointInfor[src_val].size<40)
                            Character[counter].type=10;
                        if(PointInfor[src_val].size<160&&PointInfor[src_val].size>=60)
                            Character[counter].type=4;
                        if(PointInfor[src_val].size>=160)
                            Character[counter].type=5;
                    }
                    if(dydx<=0.5)
                    {
                        if(PointInfor[src_val].size<40)
                          Character[counter].type=11;
                        if(PointInfor[src_val].size<160&&PointInfor[src_val].size>=60)
                          Character[counter].type=6;
                      if(PointInfor[src_val].size>=160)
                          Character[counter].type=7;
                    }
                }
                counter++;
                if(counter>=length)
                {
                    delete[] lpRecorder;
                    lpRecorder = nullptr;
                    return ;
                }
            }
            else
            {
                Character[counter].left = 0;
                Character[counter].bottom = 0;
                Character[counter].top = 0;
                Character[counter].right = 0;
                Character[counter].x = 0;
                Character[counter].y = 0;
            }
        }
    }
    if (counter < length-1)
    {
        for (int i = counter + 1; i < length; i++)
        {
            Character[i].left = 0;
            Character[i].bottom = 0;
            Character[i].top = 0;
            Character[i].right = 0;
            Character[i].x = 0;
            Character[i].y = 0;
        }
    }
//    ::GlobalFree(hGlobal);
    delete[] lpRecorder;
    lpRecorder = nullptr;
}

float BMPFile::Compare(CharacterVector *chara1, int Vect1, CharacterVector *chara2, int Vect2)
{
//    char* lpDIBBits = m_pBuf + m_fileHeader.bfOffBits;
    const long lWidth=512;
    const long lHeight=128;
    long lLineBytes = WIDTHBYTES(lWidth*8);

    //malloc
    char* lpRecorder = new char[
            lWidth *
            lHeight];
    if( nullptr == lpRecorder)
    {
        qWarning() << "New error";
        delete lpRecorder;
        lpRecorder = nullptr;
        return false;
    }
    memset(lpRecorder,0,lHeight*lWidth);

//    const long lWidth=512;
//    const long lHeight=128;
//    HGLOBAL	hGlobal=::GlobalAlloc(GHND,lHeight*lWidth);
//    LPSTR lpRecorder=(char*)::GlobalLock(hGlobal);
//    ::GlobalUnlock(hGlobal);
//    LONG lLineBytes=WIDTHBYTES(lWidth*8);
//    memset(lpRecorder,(unsigned char)255,lHeight*lWidth);
    for(int i=0;i<Vect2;i++)
    {
        if(chara2[i].type!=0)
        {
            LPSTR src=lpRecorder+chara2[i].y*lLineBytes+chara2[i].x;
            *src=(unsigned char)i;
        }
    }
    int maxmatchednum=0;
    for(int angle=-42;angle<42;angle++)
    {
        for(int updown=-5;updown<5;updown++)
        {
          int matchednum=0;
          bool matched=false;
          for(int m=0;m<Vect1;m++)
          {
            matched=false;
            if(chara1[m].type!=0)
            {
                long t1=chara1[m].top-updown*0.02*chara1[m].top+0.5;
                long t2=chara1[m].bottom-updown*0.02*chara1[m].bottom+0.5;
                if(t1<0)
                    t1=0;
                if(t2>lHeight-1)
                    t2=lHeight-1;
                for(long j=t1;j<=t2;j++)
                {
                    if(matched)
                       break;
                    for(long i=chara1[m].left;i<chara1[m].right;i++)
                    {
                        long t=(i+angle)%lWidth;
                        unsigned char  number=*(lpRecorder+lLineBytes*j+t);
                        if(number!=255)
                        {
                            if(chara2[number].type==chara1[m].type)
                            {
                                matched=true;
                                matchednum+=1;
                                break;
                            }
                        }
                    }
                }
            }
          }
          if(matchednum>maxmatchednum)
              maxmatchednum=matchednum;
        }
    }
//    ::GlobalFree(hGlobal);
    delete[] lpRecorder;
    lpRecorder = nullptr;
    int chara1num=0;
    int chara2num=0;
    for(int i=0;i<Vect1;i++)
    {
        if(chara1[i].type!=0)
            chara1num++;
    }
    for(int i=0;i<Vect2;i++)
    {
        if(chara2[i].type!=0)
            chara2num++;
    }
    float lamuda=(float)maxmatchednum/(float)(chara2num+chara1num);
    return  2*lamuda;
}

void BMPFile::MySaveCharaV(FileName_Chara FileName_CharaVx, int Vect)
{
    const char *filename = FileName_CharaVx.FileName.c_str();
    FILE *fp=fopen(filename,"a+");
    if( nullptr == fp )
    {
        return;
    }
    for(int i=0;i<Vect;i++)
    {
        fprintf(fp,"%4u %4u %4u %4u %4u %4u %4u\n",FileName_CharaVx.Chara[i].left,FileName_CharaVx.Chara[i].right,
            FileName_CharaVx.Chara[i].top,FileName_CharaVx.Chara[i].bottom,FileName_CharaVx.Chara[i].type,
            FileName_CharaVx.Chara[i].x,FileName_CharaVx.Chara[i].y);
    }
    fclose(fp);
}

